cell: basic mipmap filtering works now
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Oct 2008 18:11:52 +0000 (12:11 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Oct 2008 18:54:30 +0000 (12:54 -0600)
Though, only GL_MIPMAP_NEAREST / GL_LINEAR works right now.

src/gallium/drivers/cell/spu/spu_command.c
src/gallium/drivers/cell/spu/spu_funcs.c
src/gallium/drivers/cell/spu/spu_main.h
src/gallium/drivers/cell/spu/spu_texture.c
src/gallium/drivers/cell/spu/spu_texture.h

index 089af224155ef58b6146ffbd6f5c8b65f5428a95..4e98eea3389a15090c31bb87770940ad4b361650 100644 (file)
@@ -301,16 +301,18 @@ cmd_state_sampler(const struct cell_command_sampler *sampler)
    DEBUG_PRINTF("SAMPLER [%u]\n", sampler->unit);
 
    spu.sampler[sampler->unit] = sampler->state;
-#if 0
+
    if (spu.sampler[sampler->unit].min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
+      /* use lambda/lod to determine min vs. mag filter */
       spu.sample_texture4[sampler->unit] = sample_texture4_lod;
    }
-   else
-#endif
-   if (spu.sampler[sampler->unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
+   else if (spu.sampler[sampler->unit].min_img_filter
+            == PIPE_TEX_FILTER_LINEAR) {
+      /* min = mag = bilinear */
       spu.sample_texture4[sampler->unit] = sample_texture4_bilinear;
    }
    else {
+      /* min = mag = inearest */
       spu.sample_texture4[sampler->unit] = sample_texture4_nearest;
    }
 }
@@ -322,8 +324,12 @@ cmd_state_texture(const struct cell_command_texture *texture)
    const uint unit = texture->unit;
    uint i;
 
+   //if (spu.init.id==0) Debug=1;
+
    DEBUG_PRINTF("TEXTURE [%u]\n", texture->unit);
 
+   spu.texture[unit].max_level = 0;
+
    for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
       uint width = texture->width[i];
       uint height = texture->height[i];
@@ -335,14 +341,19 @@ cmd_state_texture(const struct cell_command_texture *texture)
       spu.texture[unit].level[i].width = width;
       spu.texture[unit].level[i].height = height;
 
-      spu.texture[unit].level[i].tiles_per_row = width / TILE_SIZE;
+      spu.texture[unit].level[i].tiles_per_row =
+         (width + TILE_SIZE - 1) / TILE_SIZE;
 
       spu.texture[unit].level[i].width4 = spu_splats((float) width);
       spu.texture[unit].level[i].height4 = spu_splats((float) height);
 
       spu.texture[unit].level[i].tex_size_x_mask = spu_splats(width - 1);
       spu.texture[unit].level[i].tex_size_y_mask = spu_splats(height - 1);
+
+      if (texture->start[i])
+         spu.texture[unit].max_level = i;
    }
+   //Debug=0;
 }
 
 
index f2946010bda4a602620b444b4fae39eede516342..66b82f673d5131b4d9c028d5d9ca308b89d4276f 100644 (file)
@@ -106,7 +106,7 @@ spu_txp(vector float s, vector float t, vector float r, vector float q,
         unsigned unit)
 {
    struct vec_4x4 colors;
-   spu.sample_texture4[unit](s, t, r, q, unit, colors.v);
+   spu.sample_texture4[unit](s, t, r, q, unit, 0, colors.v);
    return colors;
 }
 
index 9515543efe45cb3d46834b090a11a516714ee1c5..cfb645add02fb7801fade4a44465f786d25966aa 100644 (file)
@@ -68,7 +68,7 @@ typedef void (*spu_sample_texture4_func)(vector float s,
                                          vector float t,
                                          vector float r,
                                          vector float q,
-                                         uint unit,
+                                         uint unit, uint level,
                                          vector float colors[4]);
 
 
@@ -121,6 +121,7 @@ struct spu_texture_level
 struct spu_texture
 {
    struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
+   uint max_level;
 } ALIGN16_ATTRIB;
 
 
index 96c09e3ccbe8fbef664e303619b388655b8db73f..10036330c6c5bd4d2c65539082e0d76408e95737 100644 (file)
@@ -26,7 +26,6 @@
  **************************************************************************/
 
 
-#include <transpose_matrix4x4.h>
 #include <math.h>
 
 #include "pipe/p_compiler.h"
 void
 invalidate_tex_cache(void)
 {
-   uint lvl = 0;
-   uint unit = 0;
-   uint bytes = 4 * spu.texture[unit].level[lvl].width
-      * spu.texture[unit].level[lvl].height;
+   uint lvl;
+   for (lvl = 0; lvl < CELL_MAX_TEXTURE_LEVELS; lvl++) {
+      uint unit = 0;
+      uint bytes = 4 * spu.texture[unit].level[lvl].width
+         * spu.texture[unit].level[lvl].height;
 
-   spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
+      spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
+   }
 }
 
 
@@ -71,8 +72,8 @@ get_four_texels(uint unit, uint level, vec_uint4 x, vec_uint4 y,
 {
    const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
    const unsigned texture_ea = (uintptr_t) tlevel->start;
-   vec_uint4 tile_x = spu_rlmask(x, -5);  /* tile_x = x / 32 */
-   vec_uint4 tile_y = spu_rlmask(y, -5);  /* tile_y = y / 32 */
+   const vec_uint4 tile_x = spu_rlmask(x, -5);  /* tile_x = x / 32 */
+   const vec_uint4 tile_y = spu_rlmask(y, -5);  /* tile_y = y / 32 */
    const qword offset_x = si_andi((qword) x, 0x1f); /* offset_x = x & 0x1f */
    const qword offset_y = si_andi((qword) y, 0x1f); /* offset_y = y & 0x1f */
 
@@ -106,20 +107,19 @@ get_four_texels(uint unit, uint level, vec_uint4 x, vec_uint4 y,
 void
 sample_texture4_nearest(vector float s, vector float t,
                         vector float r, vector float q,
-                        uint unit, vector float colors[4])
+                        uint unit, uint level, vector float colors[4])
 {
-   const uint lvl = 0;
-   vector float ss = spu_mul(s, spu.texture[unit].level[lvl].width4);
-   vector float tt = spu_mul(t, spu.texture[unit].level[lvl].height4);
+   vector float ss = spu_mul(s, spu.texture[unit].level[level].width4);
+   vector float tt = spu_mul(t, spu.texture[unit].level[level].height4);
    vector unsigned int is = spu_convtu(ss, 0);
    vector unsigned int it = spu_convtu(tt, 0);
    vec_uint4 texels[4];
 
    /* PIPE_TEX_WRAP_REPEAT */
-   is = spu_and(is, spu.texture[unit].level[lvl].tex_size_x_mask);
-   it = spu_and(it, spu.texture[unit].level[lvl].tex_size_y_mask);
+   is = spu_and(is, spu.texture[unit].level[level].tex_size_x_mask);
+   it = spu_and(it, spu.texture[unit].level[level].tex_size_y_mask);
 
-   get_four_texels(unit, lvl, is, it, texels);
+   get_four_texels(unit, level, is, it, texels);
 
    /* convert four packed ARGBA pixels to float RRRR,GGGG,BBBB,AAAA */
    spu_unpack_A8R8G8B8_transpose4(texels, colors);
@@ -133,11 +133,10 @@ sample_texture4_nearest(vector float s, vector float t,
 void
 sample_texture4_bilinear(vector float s, vector float t,
                          vector float r, vector float q,
-                         uint unit, vector float colors[4])
+                         uint unit, uint level, vector float colors[4])
 {
-   const uint lvl = 0;
-   vector float ss = spu_madd(s, spu.texture[unit].level[lvl].width4,  spu_splats(-0.5f));
-   vector float tt = spu_madd(t, spu.texture[unit].level[lvl].height4, spu_splats(-0.5f));
+   vector float ss = spu_madd(s, spu.texture[unit].level[level].width4,  spu_splats(-0.5f));
+   vector float tt = spu_madd(t, spu.texture[unit].level[level].height4, spu_splats(-0.5f));
 
    vector unsigned int is0 = spu_convtu(ss, 0);
    vector unsigned int it0 = spu_convtu(tt, 0);
@@ -147,17 +146,17 @@ sample_texture4_bilinear(vector float s, vector float t,
    vector unsigned int it1 = spu_add(it0, 1);
 
    /* PIPE_TEX_WRAP_REPEAT */
-   is0 = spu_and(is0, spu.texture[unit].level[lvl].tex_size_x_mask);
-   it0 = spu_and(it0, spu.texture[unit].level[lvl].tex_size_y_mask);
-   is1 = spu_and(is1, spu.texture[unit].level[lvl].tex_size_x_mask);
-   it1 = spu_and(it1, spu.texture[unit].level[lvl].tex_size_y_mask);
+   is0 = spu_and(is0, spu.texture[unit].level[level].tex_size_x_mask);
+   it0 = spu_and(it0, spu.texture[unit].level[level].tex_size_y_mask);
+   is1 = spu_and(is1, spu.texture[unit].level[level].tex_size_x_mask);
+   it1 = spu_and(it1, spu.texture[unit].level[level].tex_size_y_mask);
 
    /* get packed int texels */
    vector unsigned int texels[16];
-   get_four_texels(unit, lvl, is0, it0, texels + 0);  /* upper-left */
-   get_four_texels(unit, lvl, is1, it0, texels + 4);  /* upper-right */
-   get_four_texels(unit, lvl, is0, it1, texels + 8);  /* lower-left */
-   get_four_texels(unit, lvl, is1, it1, texels + 12); /* lower-right */
+   get_four_texels(unit, level, is0, it0, texels + 0);  /* upper-left */
+   get_four_texels(unit, level, is1, it0, texels + 4);  /* upper-right */
+   get_four_texels(unit, level, is0, it1, texels + 8);  /* lower-left */
+   get_four_texels(unit, level, is1, it1, texels + 12); /* lower-right */
 
    /* XXX possibly rework following code to compute the weighted sample
     * colors with integer arithmetic for fewer int->float conversions.
@@ -273,14 +272,13 @@ transpose(vector unsigned int *mOut0,
  */
 void
 sample_texture4_bilinear_2(vector float s, vector float t,
-                         vector float r, vector float q,
-                         uint unit, vector float colors[4])
+                           vector float r, vector float q,
+                           uint unit, uint level, vector float colors[4])
 {
-   const uint lvl = 0;
    static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
    /* Scale texcoords by size of texture, and add half pixel bias */
-   vector float ss = spu_madd(s, spu.texture[unit].level[lvl].width4, half);
-   vector float tt = spu_madd(t, spu.texture[unit].level[lvl].height4, half);
+   vector float ss = spu_madd(s, spu.texture[unit].level[level].width4, half);
+   vector float tt = spu_madd(t, spu.texture[unit].level[level].height4, half);
 
    /* convert float coords to fixed-pt coords with 8 fraction bits */
    vector unsigned int is = spu_convtu(ss, 8);
@@ -301,17 +299,17 @@ sample_texture4_bilinear_2(vector float s, vector float t,
    vector unsigned int it1 = spu_add(it0, 1);
 
    /* PIPE_TEX_WRAP_REPEAT */
-   is0 = spu_and(is0, spu.texture[unit].level[lvl].tex_size_x_mask);
-   it0 = spu_and(it0, spu.texture[unit].level[lvl].tex_size_y_mask);
-   is1 = spu_and(is1, spu.texture[unit].level[lvl].tex_size_x_mask);
-   it1 = spu_and(it1, spu.texture[unit].level[lvl].tex_size_y_mask);
+   is0 = spu_and(is0, spu.texture[unit].level[level].tex_size_x_mask);
+   it0 = spu_and(it0, spu.texture[unit].level[level].tex_size_y_mask);
+   is1 = spu_and(is1, spu.texture[unit].level[level].tex_size_x_mask);
+   it1 = spu_and(it1, spu.texture[unit].level[level].tex_size_y_mask);
 
    /* get packed int texels */
    vector unsigned int texels[16];
-   get_four_texels(unit, lvl, is0, it0, texels + 0);  /* upper-left */
-   get_four_texels(unit, lvl, is1, it0, texels + 4);  /* upper-right */
-   get_four_texels(unit, lvl, is0, it1, texels + 8);  /* lower-left */
-   get_four_texels(unit, lvl, is1, it1, texels + 12); /* lower-right */
+   get_four_texels(unit, level, is0, it0, texels + 0);  /* upper-left */
+   get_four_texels(unit, level, is1, it0, texels + 4);  /* upper-right */
+   get_four_texels(unit, level, is0, it1, texels + 8);  /* lower-left */
+   get_four_texels(unit, level, is1, it1, texels + 12); /* lower-right */
 
    /* twiddle packed 32-bit BGRA pixels into RGBA as four unsigned ints */
    {
@@ -379,9 +377,9 @@ sample_texture4_bilinear_2(vector float s, vector float t,
 static float
 compute_lambda(uint unit, vector float s, vector float t)
 {
-   uint lvl = 0;
-   float width = spu.texture[unit].level[lvl].width;
-   float height = spu.texture[unit].level[lvl].width;
+   uint baseLevel = 0;
+   float width = spu.texture[unit].level[baseLevel].width;
+   float height = spu.texture[unit].level[baseLevel].width;
    float dsdx = width * (spu_extract(s, 1) - spu_extract(s, 0));
    float dsdy = width * (spu_extract(s, 2) - spu_extract(s, 0));
    float dtdx = height * (spu_extract(t, 1) - spu_extract(t, 0));
@@ -402,22 +400,30 @@ compute_lambda(uint unit, vector float s, vector float t)
 void
 sample_texture4_lod(vector float s, vector float t,
                     vector float r, vector float q,
-                    uint unit, vector float colors[4])
+                    uint unit, uint level, vector float colors[4])
 {
+   /*
+    * Note that we're computing a lambda/lod here that's used for all
+    * four pixels in the quad.
+    */
    float lambda = compute_lambda(unit, s, t);
 
+   /* apply lod bias */
+   lambda += spu.sampler[unit].lod_bias;
+
+   /* clamp */
    if (lambda < spu.sampler[unit].min_lod)
       lambda = spu.sampler[unit].min_lod;
    else if (lambda > spu.sampler[unit].max_lod)
       lambda = spu.sampler[unit].max_lod;
 
-   /* hack for now */
-   int level = (int) lambda;
-   if (level > 3)
-      level = 3;
+   /* convert to int level */
+   level = (int) (lambda + 0.5f);
+   ASSERT(level >= 0);
+
+   if (level > spu.texture[unit].max_level)
+      level = spu.texture[unit].max_level;
 
-   /*
    sample_texture4_bilinear_2(s, t, r, q, unit, level, colors);
-   */
 }
 
index 4802f7c47c177a8f4153feeba47f0ff9325836ee..ec06a50b4a151f11ab23e9e04ae8e853f3b70602 100644 (file)
@@ -39,24 +39,24 @@ invalidate_tex_cache(void);
 extern void
 sample_texture4_nearest(vector float s, vector float t,
                         vector float r, vector float q,
-                        uint unit, vector float colors[4]);
+                        uint unit, uint level, vector float colors[4]);
 
 
 extern void
 sample_texture4_bilinear(vector float s, vector float t,
                          vector float r, vector float q,
-                         uint unit, vector float colors[4]);
+                         uint unit, uint level, vector float colors[4]);
 
 extern void
 sample_texture4_bilinear_2(vector float s, vector float t,
                          vector float r, vector float q,
-                         uint unit, vector float colors[4]);
+                           uint unit, uint level, vector float colors[4]);
 
 
 extern void
 sample_texture4_lod(vector float s, vector float t,
                     vector float r, vector float q,
-                    uint unit, vector float colors[4]);
+                    uint unit, uint level, vector float colors[4]);
 
 
 #endif /* SPU_TEXTURE_H */