softpipe: Add functions for computing relative mipmap level
authorKrzesimir Nowak <krzesimir@kinvolk.io>
Thu, 10 Sep 2015 12:15:57 +0000 (14:15 +0200)
committerBrian Paul <brianp@vmware.com>
Thu, 10 Sep 2015 15:45:14 +0000 (09:45 -0600)
These functions will be used by textureQueryLod.

v2:

  - renamed mip_level_* funcs to mip_rel_level_* to indicate that
    these functions return mip level relative to base level and
    documented them
  - renamed a level member in sp_filter_funcs struct to relative_level
  - changed mip_rel_level_none and mip_rel_level_nearest to return mip
    level relative to base level, mip_rel_level_linear already did
    that
  - documented clamp_lod function

Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/drivers/softpipe/sp_tex_sample.c
src/gallium/drivers/softpipe/sp_tex_sample.h

index d7b656e4c97521b0a05491dab0e894992fd0bfa5..4a4cddfd3081907dd516ae89f2a3d2747748ec2e 100644 (file)
@@ -1936,6 +1936,43 @@ get_gather_component(const float lod_in[TGSI_QUAD_SIZE])
    return (*(unsigned int *)lod_in) & 0x3;
 }
 
+/**
+ * Clamps given lod to both lod limits and mip level limits. Clamping to the
+ * latter limits is done so that lod is relative to the first (base) level.
+ */
+static void
+clamp_lod(const struct sp_sampler_view *sp_sview,
+          const struct sp_sampler *sp_samp,
+          const float lod[TGSI_QUAD_SIZE],
+          float clamped[TGSI_QUAD_SIZE])
+{
+   const float min_lod = sp_samp->base.min_lod;
+   const float max_lod = sp_samp->base.max_lod;
+   const float min_level = sp_sview->base.u.tex.first_level;
+   const float max_level = sp_sview->base.u.tex.last_level;
+   int i;
+
+   for (i = 0; i < TGSI_QUAD_SIZE; i++) {
+      float cl = lod[i];
+
+      cl = CLAMP(cl, min_lod, max_lod);
+      cl = CLAMP(cl, 0, max_level - min_level);
+      clamped[i] = cl;
+   }
+}
+
+/**
+ * Get mip level relative to base level for linear mip filter
+ */
+static void
+mip_rel_level_linear(struct sp_sampler_view *sp_sview,
+                     struct sp_sampler *sp_samp,
+                     const float lod[TGSI_QUAD_SIZE],
+                     float level[TGSI_QUAD_SIZE])
+{
+   clamp_lod(sp_sview, sp_samp, lod, level);
+}
+
 static void
 mip_filter_linear(struct sp_sampler_view *sp_sview,
                   struct sp_sampler *sp_samp,
@@ -1998,6 +2035,25 @@ mip_filter_linear(struct sp_sampler_view *sp_sview,
 }
 
 
+/**
+ * Get mip level relative to base level for nearest mip filter
+ */
+static void
+mip_rel_level_nearest(struct sp_sampler_view *sp_sview,
+                      struct sp_sampler *sp_samp,
+                      const float lod[TGSI_QUAD_SIZE],
+                      float level[TGSI_QUAD_SIZE])
+{
+   int j;
+
+   clamp_lod(sp_sview, sp_samp, lod, level);
+   for (j = 0; j < TGSI_QUAD_SIZE; j++)
+      /* TODO: It should rather be:
+       * level[j] = ceil(level[j] + 0.5F) - 1.0F;
+       */
+      level[j] = (int)(level[j] + 0.5F);
+}
+
 /**
  * Compute nearest mipmap level from texcoords.
  * Then sample the texture level for four elements of a quad.
@@ -2049,6 +2105,22 @@ mip_filter_nearest(struct sp_sampler_view *sp_sview,
 }
 
 
+/**
+ * Get mip level relative to base level for none mip filter
+ */
+static void
+mip_rel_level_none(struct sp_sampler_view *sp_sview,
+                   struct sp_sampler *sp_samp,
+                   const float lod[TGSI_QUAD_SIZE],
+                   float level[TGSI_QUAD_SIZE])
+{
+   int j;
+
+   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
+      level[j] = 0;
+   }
+}
+
 static void
 mip_filter_none(struct sp_sampler_view *sp_sview,
                 struct sp_sampler *sp_samp,
@@ -2087,6 +2159,18 @@ mip_filter_none(struct sp_sampler_view *sp_sview,
 }
 
 
+/**
+ * Get mip level relative to base level for none mip filter
+ */
+static void
+mip_rel_level_none_no_filter_select(struct sp_sampler_view *sp_sview,
+                                    struct sp_sampler *sp_samp,
+                                    const float lod[TGSI_QUAD_SIZE],
+                                    float level[TGSI_QUAD_SIZE])
+{
+   mip_rel_level_none(sp_sview, sp_samp, lod, level);
+}
+
 static void
 mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
                                  struct sp_sampler *sp_samp,
@@ -2339,6 +2423,18 @@ img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
 }
 
 
+/**
+ * Get mip level relative to base level for linear mip filter
+ */
+static void
+mip_rel_level_linear_aniso(struct sp_sampler_view *sp_sview,
+                           struct sp_sampler *sp_samp,
+                           const float lod[TGSI_QUAD_SIZE],
+                           float level[TGSI_QUAD_SIZE])
+{
+   mip_rel_level_linear(sp_sview, sp_samp, lod, level);
+}
+
 /**
  * Sample 2D texture using an anisotropic filter.
  */
@@ -2450,6 +2546,17 @@ mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
    }
 }
 
+/**
+ * Get mip level relative to base level for linear mip filter
+ */
+static void
+mip_rel_level_linear_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
+                                          struct sp_sampler *sp_samp,
+                                          const float lod[TGSI_QUAD_SIZE],
+                                          float level[TGSI_QUAD_SIZE])
+{
+   mip_rel_level_linear(sp_sview, sp_samp, lod, level);
+}
 
 /**
  * Specialized version of mip_filter_linear with hard-wired calls to
@@ -2516,26 +2623,32 @@ mip_filter_linear_2d_linear_repeat_POT(
 }
 
 static const struct sp_filter_funcs funcs_linear = {
+   mip_rel_level_linear,
    mip_filter_linear
 };
 
 static const struct sp_filter_funcs funcs_nearest = {
+   mip_rel_level_nearest,
    mip_filter_nearest
 };
 
 static const struct sp_filter_funcs funcs_none = {
+   mip_rel_level_none,
    mip_filter_none
 };
 
 static const struct sp_filter_funcs funcs_none_no_filter_select = {
+   mip_rel_level_none_no_filter_select,
    mip_filter_none_no_filter_select
 };
 
 static const struct sp_filter_funcs funcs_linear_aniso = {
+   mip_rel_level_linear_aniso,
    mip_filter_linear_aniso
 };
 
 static const struct sp_filter_funcs funcs_linear_2d_linear_repeat_POT = {
+   mip_rel_level_linear_2d_linear_repeat_POT,
    mip_filter_linear_2d_linear_repeat_POT
 };
 
index 2e3976d803486fbf0dcddbd682dacd3003db65af..72b4a1ac3e87c2c5d0fdeb514941c64375985ac0 100644 (file)
@@ -86,6 +86,12 @@ typedef void (*mip_filter_func)(struct sp_sampler_view *sp_sview,
                                 const struct filter_args *args,
                                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
+
+typedef void (*mip_level_func)(struct sp_sampler_view *sp_sview,
+                               struct sp_sampler *sp_samp,
+                               const float lod[TGSI_QUAD_SIZE],
+                               float level[TGSI_QUAD_SIZE]);
+
 typedef void (*fetch_func)(struct sp_sampler_view *sp_sview,
                            const int i[TGSI_QUAD_SIZE],
                            const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
@@ -116,6 +122,7 @@ struct sp_sampler_view
 };
 
 struct sp_filter_funcs {
+   mip_level_func relative_level;
    mip_filter_func filter;
 };