v3d: don't emit point coordinates varyings if the FS doesn't read them
[mesa.git] / src / gallium / drivers / i915 / i915_state_derived.c
index c05954035710b8ccc7ed438a061f9202c7c93e42..7809010d945a0890930b9e49f33e5d782777ebf6 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2003 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i915_context.h"
 #include "i915_state.h"
 #include "i915_debug.h"
+#include "i915_fpc.h"
 #include "i915_reg.h"
 
+static uint find_mapping(const struct i915_fragment_shader* fs, int unit)
+{
+   int i;
+   for (i = 0; i < I915_TEX_UNITS ; i++)
+   {
+      if (fs->generic_mapping[i] == unit)
+         return i;
+   }
+   debug_printf("Mapping not found\n");
+   return 0;
+}
+
 
 
 /***********************************************************************
 static void calculate_vertex_layout(struct i915_context *i915)
 {
    const struct i915_fragment_shader *fs = i915->fs;
-   const enum interp_mode colorInterp = i915->rasterizer->color_interp;
    struct vertex_info vinfo;
-   boolean texCoords[8], colors[2], fog, needW;
+   boolean texCoords[I915_TEX_UNITS], colors[2], fog, needW, face;
    uint i;
    int src;
 
    memset(texCoords, 0, sizeof(texCoords));
-   colors[0] = colors[1] = fog = needW = FALSE;
+   colors[0] = colors[1] = fog = needW = face = FALSE;
    memset(&vinfo, 0, sizeof(vinfo));
 
    /* Determine which fragment program inputs are needed.  Setup HW vertex
@@ -60,38 +72,46 @@ static void calculate_vertex_layout(struct i915_context *i915)
    for (i = 0; i < fs->info.num_inputs; i++) {
       switch (fs->info.input_semantic_name[i]) {
       case TGSI_SEMANTIC_POSITION:
+         {
+            uint unit = I915_SEMANTIC_POS;
+            texCoords[find_mapping(fs, unit)] = TRUE;
+         }
          break;
       case TGSI_SEMANTIC_COLOR:
          assert(fs->info.input_semantic_index[i] < 2);
          colors[fs->info.input_semantic_index[i]] = TRUE;
          break;
       case TGSI_SEMANTIC_GENERIC:
-         /* usually a texcoord */
          {
-            const uint unit = fs->info.input_semantic_index[i];
-            assert(unit < 8);
-            texCoords[unit] = TRUE;
+            /* texcoords/varyings/other generic */
+            uint unit = fs->info.input_semantic_index[i];
+
+            texCoords[find_mapping(fs, unit)] = TRUE;
             needW = TRUE;
          }
          break;
       case TGSI_SEMANTIC_FOG:
          fog = TRUE;
          break;
+      case TGSI_SEMANTIC_FACE:
+         face = TRUE;
+         break;
       default:
+         debug_printf("Unknown input type %d\n", fs->info.input_semantic_name[i]);
          assert(0);
       }
    }
 
-   
+
    /* pos */
    src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_POSITION, 0);
    if (needW) {
-      draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src);
+      draw_emit_vertex_attr(&vinfo, EMIT_4F, src);
       vinfo.hwfmt[0] |= S4_VFMT_XYZW;
       vinfo.attrib[0].emit = EMIT_4F;
    }
    else {
-      draw_emit_vertex_attr(&vinfo, EMIT_3F, INTERP_LINEAR, src);
+      draw_emit_vertex_attr(&vinfo, EMIT_3F, src);
       vinfo.hwfmt[0] |= S4_VFMT_XYZ;
       vinfo.attrib[0].emit = EMIT_3F;
    }
@@ -102,31 +122,36 @@ static void calculate_vertex_layout(struct i915_context *i915)
    /* primary color */
    if (colors[0]) {
       src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 0);
-      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src);
+      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, src);
       vinfo.hwfmt[0] |= S4_VFMT_COLOR;
    }
 
    /* secondary color */
    if (colors[1]) {
       src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 1);
-      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src);
+      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, src);
       vinfo.hwfmt[0] |= S4_VFMT_SPEC_FOG;
    }
 
    /* fog coord, not fog blend factor */
    if (fog) {
       src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FOG, 0);
-      draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
+      draw_emit_vertex_attr(&vinfo, EMIT_1F, src);
       vinfo.hwfmt[0] |= S4_VFMT_FOG_PARAM;
    }
 
-   /* texcoords */
-   for (i = 0; i < 8; i++) {
+   /* texcoords/varyings */
+   for (i = 0; i < I915_TEX_UNITS; i++) {
       uint hwtc;
       if (texCoords[i]) {
          hwtc = TEXCOORDFMT_4D;
-         src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_GENERIC, i);
-         draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+         if (fs->generic_mapping[i] == I915_SEMANTIC_POS) {
+            src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_POSITION, 0);
+         }
+         else {
+            src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_GENERIC, fs->generic_mapping[i]);
+         }
+         draw_emit_vertex_attr(&vinfo, EMIT_4F, src);
       }
       else {
          hwtc = TEXCOORDFMT_NOT_PRESENT;
@@ -134,6 +159,20 @@ static void calculate_vertex_layout(struct i915_context *i915)
       vinfo.hwfmt[1] |= hwtc << (i * 4);
    }
 
+   /* front/back face */
+   if (face) {
+      uint slot = find_mapping(fs, I915_SEMANTIC_FACE);
+      debug_printf("Front/back face is broken\n");
+      /* XXX Because of limitations in the draw module, currently src will be 0
+       * for SEMANTIC_FACE, so this aliases to POS. We need to fix in the draw
+       * module by adding an extra shader output.
+       */
+      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FACE, 0);
+      draw_emit_vertex_attr(&vinfo, EMIT_1F, src);
+      vinfo.hwfmt[1] &= ~(TEXCOORDFMT_NOT_PRESENT << (slot * 4));
+      vinfo.hwfmt[1] |= TEXCOORDFMT_1D << (slot * 4);
+   }
+
    draw_compute_vertex_size(&vinfo);
 
    if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) {
@@ -155,40 +194,6 @@ struct i915_tracked_state i915_update_vertex_layout = {
 
 
 
-/***********************************************************************
- * Update fragment state
- */
-static void update_fs(struct i915_context *i915)
-{
-   i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
-}
-
-struct i915_tracked_state i915_hw_fs = {
-   "fs",
-   update_fs,
-   I915_NEW_FS
-};
-
-
-
-/***********************************************************************
- * Update framebuffer state
- */
-static void update_framebuffer(struct i915_context *i915)
-{
-   /* HW emit currently references framebuffer state directly:
-    */
-   i915->hardware_dirty |= I915_HW_STATIC;
-}
-
-struct i915_tracked_state i915_hw_framebuffer = {
-   "framebuffer",
-   update_framebuffer,
-   I915_NEW_FRAMEBUFFER
-};
-
-
-
 /***********************************************************************
  */
 static struct i915_tracked_state *atoms[] = {
@@ -199,6 +204,8 @@ static struct i915_tracked_state *atoms[] = {
    &i915_hw_dynamic,
    &i915_hw_fs,
    &i915_hw_framebuffer,
+   &i915_hw_dst_buf_vars,
+   &i915_hw_constants,
    NULL,
 };
 
@@ -209,6 +216,23 @@ void i915_update_derived(struct i915_context *i915)
    if (I915_DBG_ON(DBG_ATOMS))
       i915_dump_dirty(i915, __FUNCTION__);
 
+   if (!i915->fs) {
+      i915->dirty &= ~(I915_NEW_FS_CONSTANTS | I915_NEW_FS);
+      i915->hardware_dirty &= ~(I915_HW_PROGRAM | I915_HW_CONSTANTS);
+   }
+
+   if (!i915->vs)
+      i915->dirty &= ~I915_NEW_VS;
+
+   if (!i915->blend)
+      i915->dirty &= ~I915_NEW_BLEND;
+
+   if (!i915->rasterizer)
+      i915->dirty &= ~I915_NEW_RASTERIZER;
+
+   if (!i915->depth_stencil)
+      i915->dirty &= ~I915_NEW_DEPTH_STENCIL;
+   
    for (i = 0; atoms[i]; i++)
       if (atoms[i]->dirty & i915->dirty)
          atoms[i]->update(i915);