i915: Implement min/max LOD clamping with the hardware.
authorEric Anholt <eric@anholt.net>
Thu, 29 Oct 2009 18:52:28 +0000 (11:52 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 29 Oct 2009 19:06:04 +0000 (12:06 -0700)
This gets us expected behavior for clamping between mipmap levels, and
avoids relayout of textures for doing clamping.

Fixes piglit lodclamp-between.

src/mesa/drivers/dri/i915/i915_texstate.c
src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
src/mesa/drivers/dri/intel/intel_context.h
src/mesa/drivers/dri/intel/intel_tex_validate.c

index 3a20e9c3abaa16d12c7faf0f7a3f6d3e9993ad79..1397f04a59e0d2e72f963f75bbff9a61d36bcecd 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "main/mtypes.h"
 #include "main/enums.h"
+#include "main/macros.h"
 
 #include "intel_mipmap_tree.h"
 #include "intel_tex.h"
@@ -200,10 +201,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    }
 
    state[I915_TEXREG_MS4] =
-     ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK |
-       ((((intelObj->lastLevel - intelObj->firstLevel) * 4)) <<
-       MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - 1) <<
-                             MS4_VOLUME_DEPTH_SHIFT));
+      ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
+       MS4_CUBE_FACE_ENA_MASK |
+       (U_FIXED(CLAMP(tObj->MaxLod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
+       ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
 
 
    {
@@ -333,6 +334,9 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
           (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
 
       state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
+      state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(tObj->MinLod, 0.0, 11.0), 4) <<
+                                SS3_MIN_LOD_SHIFT);
+
    }
 
    /* convert border color from float to ubyte */
index 416ffc97615e97b197a2b190f7cfef7c4abfadfa..0acb027431344c7d3ce229574ea48f6268730bf2 100644 (file)
@@ -66,19 +66,6 @@ static GLuint translate_wrap_mode( GLenum wrap )
    }
 }
 
-
-static GLuint U_FIXED(GLfloat value, GLuint frac_bits)
-{
-   value *= (1<<frac_bits);
-   return value < 0 ? 0 : value;
-}
-
-static GLint S_FIXED(GLfloat value, GLuint frac_bits)
-{
-   return value * (1<<frac_bits);
-}
-
-
 static dri_bo *upload_default_color( struct brw_context *brw,
                                     const GLfloat *color )
 {
index 2778cc0136df966a03fb3b5055eb2e11bf6e1882..356fa4d1e58950dbe1780790f228891cb5e0f6cf 100644 (file)
@@ -353,6 +353,19 @@ extern char *__progname;
 #define ALIGN(value, alignment)  ((value + alignment - 1) & ~(alignment - 1))
 #define IS_POWER_OF_TWO(val) (((val) & (val - 1)) == 0)
 
+static inline uint32_t
+U_FIXED(float value, uint32_t frac_bits)
+{
+   value *= (1 << frac_bits);
+   return value < 0 ? 0 : value;
+}
+
+static inline uint32_t
+S_FIXED(float value, uint32_t frac_bits)
+{
+   return value * (1 << frac_bits);
+}
+
 #define INTEL_FIREVERTICES(intel)              \
 do {                                           \
    if ((intel)->prim.flush)                    \
index d5b562f5e57dd789a8e964a764bfdd457031e145..504993989ae5d22b0caeab23bce1b2c148e18c9e 100644 (file)
@@ -5,6 +5,7 @@
 #include "intel_batchbuffer.h"
 #include "intel_mipmap_tree.h"
 #include "intel_tex.h"
+#include "intel_chipset.h"
 
 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
 
@@ -14,7 +15,8 @@
  * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
  */
 static void
-intel_calculate_first_last_level(struct intel_texture_object *intelObj)
+intel_calculate_first_last_level(struct intel_context *intel,
+                                struct intel_texture_object *intelObj)
 {
    struct gl_texture_object *tObj = &intelObj->base;
    const struct gl_texture_image *const baseImage =
@@ -40,27 +42,27 @@ intel_calculate_first_last_level(struct intel_texture_object *intelObj)
          firstLevel = lastLevel = tObj->BaseLevel;
       }
       else {
-#ifdef I915
-         firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
-         firstLevel = MAX2(firstLevel, tObj->BaseLevel);
-         firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
-         lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
-         lastLevel = MAX2(lastLevel, tObj->BaseLevel);
-         lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
-         lastLevel = MIN2(lastLevel, tObj->MaxLevel);
-         lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */
-#else
-        /* Currently not taking min/max lod into account here, those
-         * values are programmed as sampler state elsewhere and we
-         * upload the same mipmap levels regardless.  Not sure if
-         * this makes sense as it means it isn't possible for the app
-         * to use min/max lod to reduce texture memory pressure:
-         */
-        firstLevel = tObj->BaseLevel;
-        lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2,
-                         tObj->MaxLevel);
-        lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
-#endif
+        if (!IS_9XX(intel->intelScreen->deviceID)) {
+           firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+           firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+           firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+           lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+           lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+           lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+           lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+           lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */
+        } else {
+           /* Min/max LOD are taken into account in sampler state.  We don't
+            * want to re-layout textures just because clamping has been applied
+            * since it means a bunch of blitting around and probably no memory
+            * savings (since we have to keep the other levels around anyway).
+            */
+           firstLevel = tObj->BaseLevel;
+           lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2,
+                            tObj->MaxLevel);
+           /* need at least one level */
+           lastLevel = MAX2(firstLevel, lastLevel);
+        }
       }
       break;
    case GL_TEXTURE_RECTANGLE_NV:
@@ -135,7 +137,7 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
 
    /* What levels must the tree include at a minimum?
     */
-   intel_calculate_first_last_level(intelObj);
+   intel_calculate_first_last_level(intel, intelObj);
    firstImage =
       intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);