#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.
*
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:
}
#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);
}
/* 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;
}
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);
| 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));
}
/* 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] );
}
}