Merge remote branch 'origin/gallium-st-api-dri'
[mesa.git] / src / mesa / drivers / dri / i915 / i915_fragprog.c
index 8bd761ec6a15d0554c7f0d5bad664ea77fe00ee3..15e3b87097e2d8268e96b67208e741aa4603f16f 100644 (file)
@@ -33,6 +33,7 @@
 #include "shader/prog_parameter.h"
 #include "shader/program.h"
 #include "shader/programopt.h"
+#include "shader/prog_print.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
@@ -88,7 +89,8 @@ src_vector(struct i915_fragment_program *p,
        */
    case PROGRAM_TEMPORARY:
       if (source->Index >= I915_MAX_TEMPORARY) {
-         i915_program_error(p, "Exceeded max temporary reg");
+         i915_program_error(p, "Exceeded max temporary reg: %d/%d",
+                           source->Index, I915_MAX_TEMPORARY);
          return 0;
       }
       src = UREG(REG_TYPE_R, source->Index);
@@ -120,10 +122,23 @@ src_vector(struct i915_fragment_program *p,
          src = i915_emit_decl(p, REG_TYPE_T,
                               T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0),
                               D0_CHANNEL_ALL);
+        break;
+
+      case FRAG_ATTRIB_VAR0:
+      case FRAG_ATTRIB_VAR0 + 1:
+      case FRAG_ATTRIB_VAR0 + 2:
+      case FRAG_ATTRIB_VAR0 + 3:
+      case FRAG_ATTRIB_VAR0 + 4:
+      case FRAG_ATTRIB_VAR0 + 5:
+      case FRAG_ATTRIB_VAR0 + 6:
+      case FRAG_ATTRIB_VAR0 + 7:
+         src = i915_emit_decl(p, REG_TYPE_T,
+                              T_TEX0 + (source->Index - FRAG_ATTRIB_VAR0),
+                              D0_CHANNEL_ALL);
          break;
 
       default:
-         i915_program_error(p, "Bad source->Index");
+         i915_program_error(p, "Bad source->Index: %d", source->Index);
          return 0;
       }
       break;
@@ -145,6 +160,7 @@ src_vector(struct i915_fragment_program *p,
    case PROGRAM_CONSTANT:
    case PROGRAM_STATE_VAR:
    case PROGRAM_NAMED_PARAM:
+   case PROGRAM_UNIFORM:
       src =
          i915_emit_param4fv(p,
                             program->Base.Parameters->ParameterValues[source->
@@ -152,7 +168,7 @@ src_vector(struct i915_fragment_program *p,
       break;
 
    default:
-      i915_program_error(p, "Bad source->File");
+      i915_program_error(p, "Bad source->File: %d", source->File);
       return 0;
    }
 
@@ -161,12 +177,12 @@ src_vector(struct i915_fragment_program *p,
                  GET_SWZ(source->Swizzle, 1),
                  GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3));
 
-   if (source->NegateBase)
+   if (source->Negate)
       src = negate(src,
-                   GET_BIT(source->NegateBase, 0),
-                   GET_BIT(source->NegateBase, 1),
-                   GET_BIT(source->NegateBase, 2),
-                   GET_BIT(source->NegateBase, 3));
+                   GET_BIT(source->Negate, 0),
+                   GET_BIT(source->Negate, 1),
+                   GET_BIT(source->Negate, 2),
+                   GET_BIT(source->Negate, 3));
 
    return src;
 }
@@ -179,19 +195,20 @@ get_result_vector(struct i915_fragment_program *p,
    switch (inst->DstReg.File) {
    case PROGRAM_OUTPUT:
       switch (inst->DstReg.Index) {
-      case FRAG_RESULT_COLR:
+      case FRAG_RESULT_COLOR:
          return UREG(REG_TYPE_OC, 0);
-      case FRAG_RESULT_DEPR:
+      case FRAG_RESULT_DEPTH:
          p->depth_written = 1;
          return UREG(REG_TYPE_OD, 0);
       default:
-         i915_program_error(p, "Bad inst->DstReg.Index");
+         i915_program_error(p, "Bad inst->DstReg.Index: %d",
+                           inst->DstReg.Index);
          return 0;
       }
    case PROGRAM_TEMPORARY:
       return UREG(REG_TYPE_R, inst->DstReg.Index);
    default:
-      i915_program_error(p, "Bad inst->DstReg.File");
+      i915_program_error(p, "Bad inst->DstReg.File: %d", inst->DstReg.File);
       return 0;
    }
 }
@@ -230,7 +247,7 @@ translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit)
    case TEXTURE_CUBE_INDEX:
       return D0_SAMPLE_TYPE_CUBE;
    default:
-      i915_program_error(p, "TexSrcBit");
+      i915_program_error(p, "TexSrcBit: %d", bit);
       return 0;
    }
 }
@@ -322,7 +339,8 @@ upload_program(struct i915_fragment_program *p)
       p->ctx->FragmentProgram._Current;
    const struct prog_instruction *inst = program->Base.Instructions;
 
-/*    _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */
+   if (INTEL_DEBUG & DEBUG_WM)
+      _mesa_print_program(&program->Base);
 
    /* Is this a parse-failed program?  Ensure a valid program is
     * loaded, as the flagging of an error isn't sufficient to stop
@@ -349,7 +367,7 @@ upload_program(struct i915_fragment_program *p)
 
    while (1) {
       GLuint src0, src1, src2, flags;
-      GLuint tmp = 0, consts0 = 0, consts1 = 0;
+      GLuint tmp = 0, dst, consts0 = 0, consts1 = 0;
 
       switch (inst->Opcode) {
       case OPCODE_ABS:
@@ -501,6 +519,10 @@ upload_program(struct i915_fragment_program *p)
          EMIT_1ARG_ARITH(A0_FLR);
          break;
 
+      case OPCODE_TRUNC:
+        EMIT_1ARG_ARITH(A0_TRC);
+        break;
+
       case OPCODE_FRC:
          EMIT_1ARG_ARITH(A0_FRC);
          break;
@@ -514,6 +536,22 @@ upload_program(struct i915_fragment_program *p)
                          0, src0, T0_TEXKILL);
          break;
 
+      case OPCODE_KIL_NV:
+        if (inst->DstReg.CondMask == COND_TR) {
+           tmp = i915_get_utemp(p);
+
+           i915_emit_texld(p, get_live_regs(p, inst),
+                           tmp, A0_DEST_CHANNEL_ALL,
+                           0, /* use a dummy dest reg */
+                           swizzle(tmp, ONE, ONE, ONE, ONE), /* always */
+                           T0_TEXKILL);
+        } else {
+           p->error = 1;
+           i915_program_error(p, "Unsupported KIL_NV condition code: %d",
+                              inst->DstReg.CondMask);
+        }
+        break;
+
       case OPCODE_LG2:
          src0 = src_vector(p, &inst->SrcReg[0], program);
 
@@ -613,6 +651,20 @@ upload_program(struct i915_fragment_program *p)
          EMIT_2ARG_ARITH(A0_MUL);
          break;
 
+      case OPCODE_NOISE1:
+      case OPCODE_NOISE2:
+      case OPCODE_NOISE3:
+      case OPCODE_NOISE4:
+        /* Don't implement noise because we just don't have the instructions
+         * to spare.  We aren't the first vendor to do so.
+         */
+        i915_program_error(p, "Stubbed-out noise functions");
+        i915_emit_arith(p,
+                        A0_MOV,
+                        get_result_vector(p, inst),
+                        get_result_flags(inst), 0,
+                        swizzle(tmp, ZERO, ZERO, ZERO, ZERO), 0, 0);
+
       case OPCODE_POW:
          src0 = src_vector(p, &inst->SrcReg[0], program);
          src1 = src_vector(p, &inst->SrcReg[1], program);
@@ -719,9 +771,38 @@ upload_program(struct i915_fragment_program *p)
          }
          break;
 
-      case OPCODE_SGE:
-         EMIT_2ARG_ARITH(A0_SGE);
-         break;
+      case OPCODE_SEQ:
+        tmp = i915_get_utemp(p);
+        flags = get_result_flags(inst);
+        dst = get_result_vector(p, inst);
+
+        /* dst = src1 >= src2 */
+        i915_emit_arith(p,
+                        A0_SGE,
+                        dst,
+                        flags, 0,
+                        src_vector(p, &inst->SrcReg[0], program),
+                        src_vector(p, &inst->SrcReg[1], program),
+                        0);
+        /* tmp = src1 <= src2 */
+        i915_emit_arith(p,
+                        A0_SGE,
+                        tmp,
+                        flags, 0,
+                        negate(src_vector(p, &inst->SrcReg[0], program),
+                               1, 1, 1, 1),
+                        negate(src_vector(p, &inst->SrcReg[1], program),
+                               1, 1, 1, 1),
+                        0);
+        /* dst = tmp && dst */
+        i915_emit_arith(p,
+                        A0_MUL,
+                        dst,
+                        flags, 0,
+                        dst,
+                        tmp,
+                        0);
+        break;
 
       case OPCODE_SIN:
          src0 = src_vector(p, &inst->SrcReg[0], program);
@@ -807,10 +888,71 @@ upload_program(struct i915_fragment_program *p)
 
          break;
 
+      case OPCODE_SGE:
+        EMIT_2ARG_ARITH(A0_SGE);
+        break;
+
+      case OPCODE_SGT:
+        i915_emit_arith(p,
+                        A0_SLT,
+                        get_result_vector( p, inst ),
+                        get_result_flags( inst ), 0,
+                        negate(src_vector( p, &inst->SrcReg[0], program),
+                               1, 1, 1, 1),
+                        negate(src_vector( p, &inst->SrcReg[1], program),
+                               1, 1, 1, 1),
+                        0);
+         break;
+
+      case OPCODE_SLE:
+        i915_emit_arith(p,
+                        A0_SGE,
+                        get_result_vector( p, inst ),
+                        get_result_flags( inst ), 0,
+                        negate(src_vector( p, &inst->SrcReg[0], program),
+                               1, 1, 1, 1),
+                        negate(src_vector( p, &inst->SrcReg[1], program),
+                               1, 1, 1, 1),
+                        0);
+         break;
+
       case OPCODE_SLT:
          EMIT_2ARG_ARITH(A0_SLT);
          break;
 
+      case OPCODE_SNE:
+        tmp = i915_get_utemp(p);
+        flags = get_result_flags(inst);
+        dst = get_result_vector(p, inst);
+
+        /* dst = src1 < src2 */
+        i915_emit_arith(p,
+                        A0_SLT,
+                        dst,
+                        flags, 0,
+                        src_vector(p, &inst->SrcReg[0], program),
+                        src_vector(p, &inst->SrcReg[1], program),
+                        0);
+        /* tmp = src1 > src2 */
+        i915_emit_arith(p,
+                        A0_SLT,
+                        tmp,
+                        flags, 0,
+                        negate(src_vector(p, &inst->SrcReg[0], program),
+                               1, 1, 1, 1),
+                        negate(src_vector(p, &inst->SrcReg[1], program),
+                               1, 1, 1, 1),
+                        0);
+        /* dst = tmp || dst */
+        i915_emit_arith(p,
+                        A0_ADD,
+                        dst,
+                        flags | A0_DEST_SATURATE, 0,
+                        dst,
+                        tmp,
+                        0);
+         break;
+
       case OPCODE_SUB:
          src0 = src_vector(p, &inst->SrcReg[0], program);
          src1 = src_vector(p, &inst->SrcReg[1], program);
@@ -867,8 +1009,39 @@ upload_program(struct i915_fragment_program *p)
       case OPCODE_END:
          return;
 
+      case OPCODE_BGNLOOP:
+      case OPCODE_BGNSUB:
+      case OPCODE_BRA:
+      case OPCODE_BRK:
+      case OPCODE_CAL:
+      case OPCODE_CONT:
+      case OPCODE_DDX:
+      case OPCODE_DDY:
+      case OPCODE_ELSE:
+      case OPCODE_ENDIF:
+      case OPCODE_ENDLOOP:
+      case OPCODE_ENDSUB:
+      case OPCODE_IF:
+      case OPCODE_RET:
+        p->error = 1;
+        i915_program_error(p, "Unsupported opcode: %s",
+                           _mesa_opcode_string(inst->Opcode));
+        return;
+
+      case OPCODE_EXP:
+      case OPCODE_LOG:
+        /* These opcodes are claimed as GLSL, NV_vp, and ARB_vp in
+         * prog_instruction.h, but apparently GLSL doesn't ever emit them.
+         * Instead, it translates to EX2 or LG2.
+         */
+      case OPCODE_TXD:
+      case OPCODE_TXL:
+        /* These opcodes are claimed by GLSL in prog_instruction.h, but
+         * only NV_vp/fp appears to emit them.
+         */
       default:
-         i915_program_error(p, "bad opcode");
+         i915_program_error(p, "bad opcode: %s",
+                           _mesa_opcode_string(inst->Opcode));
          return;
       }
 
@@ -904,7 +1077,7 @@ check_wpos(struct i915_fragment_program *p)
    p->wpos_tex = -1;
 
    for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
-      if (inputs & FRAG_BIT_TEX(i))
+      if (inputs & (FRAG_BIT_TEX(i) | FRAG_BIT_VAR(i)))
          continue;
       else if (inputs & FRAG_BIT_WPOS) {
          p->wpos_tex = i;
@@ -1032,7 +1205,7 @@ i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
       return GL_TRUE;
 }
 
-static void
+static GLboolean
 i915ProgramStringNotify(GLcontext * ctx,
                         GLenum target, struct gl_program *prog)
 {
@@ -1050,9 +1223,34 @@ i915ProgramStringNotify(GLcontext * ctx,
       }
    }
 
-   _tnl_program_string(ctx, target, prog);
+   (void) _tnl_program_string(ctx, target, prog);
+
+   /* XXX check if program is legal, within limits */
+   return GL_TRUE;
 }
 
+void
+i915_update_program(GLcontext *ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   struct i915_fragment_program *fp =
+      (struct i915_fragment_program *) ctx->FragmentProgram._Current;
+
+   if (i915->current_program != fp) {
+      if (i915->current_program) {
+         i915->current_program->on_hardware = 0;
+         i915->current_program->params_uptodate = 0;
+      }
+
+      i915->current_program = fp;
+   }
+
+   if (!fp->translated)
+      translate_program(fp);
+
+   FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, fp->error);
+}
 
 void
 i915ValidateFragmentProgram(struct i915_context *i915)
@@ -1070,16 +1268,6 @@ i915ValidateFragmentProgram(struct i915_context *i915)
    GLuint s2 = S2_TEXCOORD_NONE;
    int i, offset = 0;
 
-   if (i915->current_program != p) {
-      if (i915->current_program) {
-         i915->current_program->on_hardware = 0;
-         i915->current_program->params_uptodate = 0;
-      }
-
-      i915->current_program = p;
-   }
-
-
    /* Important:
     */
    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
@@ -1105,40 +1293,32 @@ i915ValidateFragmentProgram(struct i915_context *i915)
       EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4);
    }
 
-   if ((inputsRead & (FRAG_BIT_COL1 | FRAG_BIT_FOGC)) ||
-       i915->vertex_fog != I915_FOG_NONE) {
-
-      if (inputsRead & FRAG_BIT_COL1) {
-         intel->specoffset = offset / 4;
-         EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3);
-      }
-      else
-         EMIT_PAD(3);
-
-      if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE)
-         EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1);
-      else
-         EMIT_PAD(1);
+   if (inputsRead & FRAG_BIT_COL1) {
+       intel->specoffset = offset / 4;
+       EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_4UB_4F_BGRA, S4_VFMT_SPEC_FOG, 4);
    }
 
-   /* XXX this was disabled, but enabling this code helped fix the Glean
-    * tfragprog1 fog tests.
-    */
-#if 1
    if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) {
       EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4);
    }
-#endif
 
    for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
       if (inputsRead & FRAG_BIT_TEX(i)) {
-         int sz = VB->TexCoordPtr[i]->size;
+         int sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size;
 
          s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
          s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
 
          EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4);
       }
+      else if (inputsRead & FRAG_BIT_VAR(i)) {
+         int sz = VB->AttribPtr[_TNL_ATTRIB_GENERIC0 + i]->size;
+
+         s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
+         s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
+
+         EMIT_ATTR(_TNL_ATTRIB_GENERIC0 + i, EMIT_SZ(sz), 0, sz * 4);
+      }
       else if (i == p->wpos_tex) {
 
          /* If WPOS is required, duplicate the XYZ position data in an