radeon/r200: drop legacy texture heap code
[mesa.git] / src / mesa / drivers / dri / r200 / r200_vertprog.c
index 9ac7a96827adeb6a3aa8871876419ba65c94f775..888f91db73d21149a9f5c936e44b9ef6cc2b640a 100644 (file)
@@ -30,18 +30,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Aapo Tahkola <aet@rasterburn.org>
  *   Roland Scheidegger <rscheidegger_lists@hispeed.ch>
  */
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
-#include "program.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "shader/programopt.h"
+#include "tnl/tnl.h"
 
 #include "r200_context.h"
 #include "r200_vertprog.h"
 #include "r200_ioctl.h"
 #include "r200_tcl.h"
-#include "program_instruction.h"
-#include "programopt.h"
-#include "tnl/tnl.h"
 
 #if SWIZZLE_X != VSF_IN_COMPONENT_X || \
     SWIZZLE_Y != VSF_IN_COMPONENT_Y || \
@@ -152,7 +154,7 @@ static GLboolean r200VertexProgUpdateParams(GLcontext *ctx, struct r200_vertex_p
    return GL_TRUE;
 }
 
-static __inline unsigned long t_dst_mask(GLuint mask)
+static INLINE unsigned long t_dst_mask(GLuint mask)
 {
    /* WRITEMASK_* is equivalent to VSF_FLAG_* */
    return mask & VSF_FLAG_ALL;
@@ -213,6 +215,7 @@ static unsigned long t_src_class(enum register_file file)
    case PROGRAM_LOCAL_PARAM:
    case PROGRAM_ENV_PARAM:
    case PROGRAM_NAMED_PARAM:
+   case PROGRAM_CONSTANT:
    case PROGRAM_STATE_VAR:
       return VSF_IN_CLASS_PARAM;
    /*
@@ -226,7 +229,7 @@ static unsigned long t_src_class(enum register_file file)
    }
 }
 
-static __inline unsigned long t_swizzle(GLubyte swizzle)
+static INLINE unsigned long t_swizzle(GLubyte swizzle)
 {
 /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
    return swizzle;
@@ -404,6 +407,9 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
    unsigned long hw_op;
    int dofogfix = 0;
    int fog_temp_i = 0;
+   int free_inputs;
+   int array_count = 0;
+   int u_temp_used;
 
    vp->native = GL_FALSE;
    vp->translated = GL_TRUE;
@@ -412,6 +418,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
    if (mesa_vp->Base.NumInstructions == 0)
       return GL_FALSE;
 
+#if 0
    if ((mesa_vp->Base.InputsRead &
       ~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 |
       VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 |
@@ -422,6 +429,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
       }
       return GL_FALSE;
    }
+#endif
 
    if ((mesa_vp->Base.OutputsWritten &
       ~((1 << VERT_RESULT_HPOS) | (1 << VERT_RESULT_COL0) | (1 << VERT_RESULT_COL1) |
@@ -456,9 +464,9 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
 
    /* for fogc, can't change mesa_vp, as it would hose swtnl, and exp with
       base e isn't directly available neither. */
-   if (mesa_vp->Base.OutputsWritten & VERT_RESULT_FOGC && !vp->fogpidx) {
+   if ((mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) && !vp->fogpidx) {
       struct gl_program_parameter_list *paramList;
-      GLint tokens[6] = { STATE_FOG_PARAMS, 0, 0, 0, 0, 0 };
+      gl_state_index tokens[STATE_LENGTH] = { STATE_FOG_PARAMS, 0, 0, 0, 0 };
       paramList = mesa_vp->Base.Parameters;
       vp->fogpidx = _mesa_add_state_reference(paramList, tokens);
    }
@@ -470,35 +478,97 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
    else
       mesa_vp->Base.NumNativeParameters = 0;
 
-   for(i=0; i < VERT_ATTRIB_MAX; i++)
+   for(i = 0; i < VERT_ATTRIB_MAX; i++)
       vp->inputs[i] = -1;
+   for(i = 0; i < 15; i++)
+      vp->inputmap_rev[i] = 255;
+   free_inputs = 0x2ffd;
+
 /* fglrx uses fixed inputs as follows for conventional attribs.
-   generic attribs use non-fixed assignment, fglrx will always use the lowest attrib values available.
-   There are 12 generic attribs possible, corresponding to attrib 0, 2-11 and 13 in a hw vertex prog.
-   attr 1 and 12 are not available for generic attribs as those cannot be made vec4 (correspond to
-   vertex normal/weight)
+   generic attribs use non-fixed assignment, fglrx will always use the
+   lowest attrib values available. We'll just do the same.
+   There are 12 generic attribs possible, corresponding to attrib 0, 2-11
+   and 13 in a hw vertex prog.
+   attr 1 and 12 aren't used for generic attribs as those cannot be made vec4
+   (correspond to vertex normal/weight - maybe weight actually could be made vec4).
+   Additionally, not more than 12 arrays in total are possible I think.
    attr 0 is pos, R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0
    attr 2-5 use colors 0-3 (R200_VTX_FP_RGBA << R200_VTX_COLOR_0/1/2/3_SHIFT in R200_SE_VTX_FMT_0)
    attr 6-11 use tex 0-5 (4 << R200_VTX_TEX0/1/2/3/4/5_COMP_CNT_SHIFT in R200_SE_VTX_FMT_1)
    attr 13 uses vtx1 pos (R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0)
-   generic attribs would require some more work (dma regions, renaming). */
+*/
 
-/* may look different when using idx buf / input_route instead of se_vtx_fmt? */
-   vp->inputs[VERT_ATTRIB_POS] = 0;
-   vp->inputs[VERT_ATTRIB_WEIGHT] = 12;
-   vp->inputs[VERT_ATTRIB_NORMAL] = 1;
-   vp->inputs[VERT_ATTRIB_COLOR0] = 2;
-   vp->inputs[VERT_ATTRIB_COLOR1] = 3;
-   vp->inputs[VERT_ATTRIB_FOG] = 15;
-   vp->inputs[VERT_ATTRIB_TEX0] = 6;
-   vp->inputs[VERT_ATTRIB_TEX1] = 7;
-   vp->inputs[VERT_ATTRIB_TEX2] = 8;
-   vp->inputs[VERT_ATTRIB_TEX3] = 9;
-   vp->inputs[VERT_ATTRIB_TEX4] = 10;
-   vp->inputs[VERT_ATTRIB_TEX5] = 11;
 /* attr 4,5 and 13 are only used with generic attribs.
    Haven't seen attr 14 used, maybe that's for the hw pointsize vec1 (which is
    not possibe to use with vertex progs as it is lacking in vert prog specification) */
+/* may look different when using idx buf / input_route instead of se_vtx_fmt? */
+   if (mesa_vp->Base.InputsRead & VERT_BIT_POS) {
+      vp->inputs[VERT_ATTRIB_POS] = 0;
+      vp->inputmap_rev[0] = VERT_ATTRIB_POS;
+      free_inputs &= ~(1 << 0);
+      array_count++;
+   }
+   if (mesa_vp->Base.InputsRead & VERT_BIT_WEIGHT) {
+      vp->inputs[VERT_ATTRIB_WEIGHT] = 12;
+      vp->inputmap_rev[1] = VERT_ATTRIB_WEIGHT;
+      array_count++;
+   }
+   if (mesa_vp->Base.InputsRead & VERT_BIT_NORMAL) {
+      vp->inputs[VERT_ATTRIB_NORMAL] = 1;
+      vp->inputmap_rev[2] = VERT_ATTRIB_NORMAL;
+      array_count++;
+   }
+   if (mesa_vp->Base.InputsRead & VERT_BIT_COLOR0) {
+      vp->inputs[VERT_ATTRIB_COLOR0] = 2;
+      vp->inputmap_rev[4] = VERT_ATTRIB_COLOR0;
+      free_inputs &= ~(1 << 2);
+      array_count++;
+   }
+   if (mesa_vp->Base.InputsRead & VERT_BIT_COLOR1) {
+      vp->inputs[VERT_ATTRIB_COLOR1] = 3;
+      vp->inputmap_rev[5] = VERT_ATTRIB_COLOR1;
+      free_inputs &= ~(1 << 3);
+      array_count++;
+   }
+   if (mesa_vp->Base.InputsRead & VERT_BIT_FOG) {
+      vp->inputs[VERT_ATTRIB_FOG] = 15; array_count++;
+      vp->inputmap_rev[3] = VERT_ATTRIB_FOG;
+      array_count++;
+   }
+   for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX5; i++) {
+      if (mesa_vp->Base.InputsRead & (1 << i)) {
+        vp->inputs[i] = i - VERT_ATTRIB_TEX0 + 6;
+        vp->inputmap_rev[8 + i - VERT_ATTRIB_TEX0] = i;
+        free_inputs &= ~(1 << (i - VERT_ATTRIB_TEX0 + 6));
+        array_count++;
+      }
+   }
+   /* using VERT_ATTRIB_TEX6/7 would be illegal */
+   /* completely ignore aliasing? */
+   for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
+      int j;
+   /* completely ignore aliasing? */
+      if (mesa_vp->Base.InputsRead & (1 << i)) {
+        array_count++;
+        if (array_count > 12) {
+           if (R200_DEBUG & DEBUG_FALLBACKS) {
+              fprintf(stderr, "more than 12 attribs used in vert prog\n");
+           }
+           return GL_FALSE;
+        }
+        for (j = 0; j < 14; j++) {
+           /* will always find one due to limited array_count */
+           if (free_inputs & (1 << j)) {
+              free_inputs &= ~(1 << j);
+              vp->inputs[i] = j;
+              if (j == 0) vp->inputmap_rev[j] = i; /* mapped to pos */
+              else if (j < 12) vp->inputmap_rev[j + 2] = i; /* mapped to col/tex */
+              else vp->inputmap_rev[j + 1] = i; /* mapped to pos1 */
+              break;
+           }
+        }
+      }
+   }
 
    if (!(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {
       if (R200_DEBUG & DEBUG_FALLBACKS) {
@@ -506,6 +576,12 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
       }
       return GL_FALSE;
    }
+   if (free_inputs & 1) {
+      if (R200_DEBUG & DEBUG_FALLBACKS) {
+        fprintf(stderr, "can't handle vert prog without position input\n");
+      }
+      return GL_FALSE;
+   }
 
    o_inst = vp->instr;
    for (vpi = mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){
@@ -670,9 +746,16 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
         goto next;
 
       case OPCODE_MAD:
+        /* only 2 read ports into temp memory thus may need the macro op MAD_2
+           instead (requiring 2 clocks) if all inputs are in temp memory
+           (and, only if they actually reference 3 distinct temps) */
         hw_op=(src[0].File == PROGRAM_TEMPORARY &&
            src[1].File == PROGRAM_TEMPORARY &&
-           src[2].File == PROGRAM_TEMPORARY) ? R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
+           src[2].File == PROGRAM_TEMPORARY &&
+           (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index)) &&
+           (((src[0].RelAddr << 8) | src[0].Index) != ((src[2].RelAddr << 8) | src[2].Index)) &&
+           (((src[1].RelAddr << 8) | src[1].Index) != ((src[2].RelAddr << 8) | src[2].Index))) ?
+           R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
 
         o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
            t_dst_mask(dst.WriteMask));
@@ -800,8 +883,11 @@ else {
       case OPCODE_XPD:
         /* mul r0, r1.yzxw, r2.zxyw
            mad r0, -r2.yzxw, r1.zxyw, r0
-           NOTE: might need MAD_2
          */
+        hw_op=(src[0].File == PROGRAM_TEMPORARY &&
+           src[1].File == PROGRAM_TEMPORARY &&
+           (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index))) ?
+           R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
 
         o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
            (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
@@ -827,7 +913,7 @@ else {
         o_inst++;
         u_temp_i--;
 
-        o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MAD, t_dst(&dst),
+        o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
                t_dst_mask(dst.WriteMask));
 
         o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
@@ -977,14 +1063,15 @@ else {
          dofogfix = 0;
       }
 
+      u_temp_used = (R200_VSF_MAX_TEMPS - 1) - u_temp_i;
       if (mesa_vp->Base.NumNativeTemporaries <
-        (mesa_vp->Base.NumTemporaries + (R200_VSF_MAX_TEMPS - 1 - u_temp_i))) {
+        (mesa_vp->Base.NumTemporaries + u_temp_used)) {
         mesa_vp->Base.NumNativeTemporaries =
-           mesa_vp->Base.NumTemporaries + (R200_VSF_MAX_TEMPS - 1 - u_temp_i);
+           mesa_vp->Base.NumTemporaries + u_temp_used;
       }
-      if (u_temp_i < mesa_vp->Base.NumTemporaries) {
+      if ((mesa_vp->Base.NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) {
         if (R200_DEBUG & DEBUG_FALLBACKS) {
-           fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->Base.NumTemporaries, u_temp_i);
+           fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->Base.NumTemporaries, u_temp_used);
         }
         return GL_FALSE;
       }
@@ -1023,9 +1110,9 @@ void r200SetupVertexProg( GLcontext *ctx ) {
    }
    /* could optimize setting up vertex progs away for non-tcl hw */
    fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp) &&
-      rmesa->r200Screen->drmSupportsVertexProgram);
+      rmesa->radeon.radeonScreen->drmSupportsVertexProgram);
    TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback);
-   if (rmesa->TclFallback) return;
+   if (rmesa->radeon.TclFallback) return;
 
    R200_STATECHANGE( rmesa, vap );
    /* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it?
@@ -1145,6 +1232,9 @@ r200ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog)
       r200_translate_vertex_program(ctx, vp);
       rmesa->curr_vp_hw = NULL;
       break;
+   case GL_FRAGMENT_SHADER_ATI:
+      rmesa->afs_loaded = NULL;
+      break;
    }
    /* need this for tcl fallbacks */
    _tnl_program_string(ctx, target, prog);