i915: Max and Min lod now works
authorJakob Bornecrantz <jakob@tungstengraphics.com>
Tue, 17 Jun 2008 13:47:01 +0000 (15:47 +0200)
committerJakob Bornecrantz <jakob@tungstengraphics.com>
Tue, 17 Jun 2008 13:47:01 +0000 (15:47 +0200)
src/gallium/drivers/i915simple/i915_context.h
src/gallium/drivers/i915simple/i915_state.c
src/gallium/drivers/i915simple/i915_state_sampler.c

index 2ee0381648d1e2a37ab68322b9833e89262885bb..892a88fd2cc54491388f5e2a637281c2636a2f69 100644 (file)
@@ -178,6 +178,8 @@ struct i915_rasterizer_state {
 struct i915_sampler_state {
    unsigned state[3];
    const struct pipe_sampler_state *templ;
+   unsigned minlod;
+   unsigned maxlod;
 };
 
 
index 39d5d5e9d65b3d8f3e409935a573823b70c9991c..dbb33f26955f7aed7eedfaea901926fc0d23b231 100644 (file)
@@ -251,11 +251,17 @@ i915_create_sampler_state(struct pipe_context *pipe,
    if (sampler->normalized_coords)
       cso->state[1] |= SS3_NORMALIZED_COORDS;
 
-   if (0) /* XXX not tested yet */
    {
       int minlod = (int) (16.0 * sampler->min_lod);
+      int maxlod = (int) (16.0 * sampler->max_lod);
       minlod = CLAMP(minlod, 0, 16 * 11);
-      cso->state[1] |= (minlod << SS3_MIN_LOD_SHIFT);
+      maxlod = CLAMP(maxlod, 0, 16 * 11);
+
+      if (minlod > maxlod)
+        maxlod = minlod;
+
+      cso->minlod = minlod;
+      cso->maxlod = maxlod;
    }
 
    {
index 982eec4a1b082b79ff0436fde7b74ea48a04db07..fbdc1a3b68c2866311716ac341f7d3e94bb03b92 100644 (file)
 #include "i915_state.h"
 
 
+/*
+ * A note about min_lod & max_lod.
+ *
+ * There is a circular dependancy between the sampler state
+ * and the map state to be submitted to hw.
+ *
+ * Two condition must be meet:
+ * min_lod =< max_lod == true
+ * max_lod =< last_level == true
+ *
+ *
+ * This is all fine and dandy if it where for the fact that max_lod
+ * is set on the map state instead of the sampler state. That is
+ * the max_lod we submit on map is:
+ * max_lod = MIN2(last_level, max_lod);
+ *
+ * So we need to update the map state when we change samplers and
+ * we need to be change the sampler state when map state is changed.
+ * The first part is done by calling i915_update_texture in
+ * i915_update_samplers and the second part is done else where in
+ * code tracking the state changes.
+ */
+
+static void
+i915_update_texture(struct i915_context *i915,
+                    uint unit,
+                    const struct i915_texture *tex,
+                    const struct i915_sampler_state *sampler,
+                    uint state[6]);
 /**
  * Compute i915 texture sampling state.
  *
@@ -50,6 +79,7 @@ static void update_sampler(struct i915_context *i915,
                           unsigned state[3] )
 {
    const struct pipe_texture *pt = &tex->base;
+   unsigned minlod, lastlod;
 
    /* Need to do this after updating the maps, which call the
     * intel_finalize_mipmap_tree and hence can update firstLevel:
@@ -95,6 +125,15 @@ static void update_sampler(struct i915_context *i915,
    }
 #endif
 
+   /* See note at the top of file */
+   minlod = sampler->minlod;
+   lastlod = pt->last_level << 4;
+
+   if (lastlod < minlod) {
+      minlod = lastlod;
+   }
+
+   state[1] |= (sampler->minlod << SS3_MIN_LOD_SHIFT);
    state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
 }
 
@@ -112,18 +151,23 @@ void i915_update_samplers( struct i915_context *i915 )
       /* could also examine the fragment program? */
       if (i915->texture[unit]) {
         update_sampler( i915,
-                         unit,
-                         i915->sampler[unit],       /* sampler state */
-                         i915->texture[unit],        /* texture */
-                        i915->current.sampler[unit] /* the result */
-                         );
-
-         i915->current.sampler_enable_nr++;
-         i915->current.sampler_enable_flags |= (1 << unit);
+                        unit,
+                        i915->sampler[unit],       /* sampler state */
+                        i915->texture[unit],        /* texture */
+                        i915->current.sampler[unit] /* the result */
+                        );
+        i915_update_texture( i915,
+                             unit,
+                             i915->texture[unit],          /* texture */
+                             i915->sampler[unit],          /* sampler state */
+                             i915->current.texbuffer[unit] );
+
+        i915->current.sampler_enable_nr++;
+        i915->current.sampler_enable_flags |= (1 << unit);
       }
    }
 
-   i915->hardware_dirty |= I915_HW_SAMPLER;
+   i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP;
 }
 
 
@@ -179,14 +223,17 @@ translate_texture_format(enum pipe_format pipeFormat)
 
 
 static void
-i915_update_texture(struct i915_context *i915, uint unit,
+i915_update_texture(struct i915_context *i915,
+                    uint unit,
+                    const struct i915_texture *tex,
+                    const struct i915_sampler_state *sampler,
                     uint state[6])
 {
-   const struct i915_texture *tex = i915->texture[unit];
    const struct pipe_texture *pt = &tex->base;
    uint format, pitch;
    const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
    const uint num_levels = pt->last_level;
+   unsigned max_lod = num_levels * 4;
 
    assert(tex);
    assert(width);
@@ -207,16 +254,19 @@ i915_update_texture(struct i915_context *i915, uint unit,
        | MS3_USE_FENCE_REGS);
 
    /*
-    * XXX sampler->max_lod should be used to program the MAX_LOD field below.
-    * Also, when min_filter != mag_filter and there's just one mipmap level,
+    * XXX When min_filter != mag_filter and there's just one mipmap level,
     * set max_lod = 1 to make sure i915 chooses between min/mag filtering.
     */
 
+   /* See note at the top of file */
+   if (max_lod > (sampler->maxlod >> 2))
+      max_lod = sampler->maxlod >> 2;
+
    /* MS4 state */
    state[1] =
       ((((pitch / 4) - 1) << MS4_PITCH_SHIFT)
        | MS4_CUBE_FACE_ENA_MASK
-       | ((num_levels * 4) << MS4_MAX_LOD_SHIFT)
+       | ((max_lod) << MS4_MAX_LOD_SHIFT)
        | ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
 }
 
@@ -231,7 +281,11 @@ i915_update_textures(struct i915_context *i915)
       /* determine unit enable/disable by looking for a bound texture */
       /* could also examine the fragment program? */
       if (i915->texture[unit]) {
-         i915_update_texture(i915, unit, i915->current.texbuffer[unit]);
+        i915_update_texture( i915,
+                             unit,
+                             i915->texture[unit],          /* texture */
+                             i915->sampler[unit],          /* sampler state */
+                             i915->current.texbuffer[unit] );
       }
    }