summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/cell/spu
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-10-13 16:43:11 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-10-13 16:43:36 -0600
commit978799beb2a9c51550abb1f37bb6f63d06bc4717 (patch)
tree56e725b9d9f7e9ce03891ff89206aa7bc02cd07a /src/gallium/drivers/cell/spu
parentb0c136cfb1fcbcea35e17dc699a96acbb24738f5 (diff)
cell: initial work for mipmap texture filtering
Diffstat (limited to 'src/gallium/drivers/cell/spu')
-rw-r--r--src/gallium/drivers/cell/spu/spu_command.c37
-rw-r--r--src/gallium/drivers/cell/spu/spu_funcs.c1
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h7
-rw-r--r--src/gallium/drivers/cell/spu/spu_texture.c120
-rw-r--r--src/gallium/drivers/cell/spu/spu_texture.h6
5 files changed, 126 insertions, 45 deletions
diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c
index 64890f6dbd..089af22415 100644
--- a/src/gallium/drivers/cell/spu/spu_command.c
+++ b/src/gallium/drivers/cell/spu/spu_command.c
@@ -301,6 +301,12 @@ 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) {
+ spu.sample_texture4[sampler->unit] = sample_texture4_lod;
+ }
+ else
+#endif
if (spu.sampler[sampler->unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
spu.sample_texture4[sampler->unit] = sample_texture4_bilinear;
}
@@ -314,24 +320,29 @@ static void
cmd_state_texture(const struct cell_command_texture *texture)
{
const uint unit = texture->unit;
- const uint width = texture->width;
- const uint height = texture->height;
+ uint i;
- DEBUG_PRINTF("TEXTURE [%u] at %p size %u x %u\n",
- texture->unit, texture->start,
- texture->width, texture->height);
+ DEBUG_PRINTF("TEXTURE [%u]\n", texture->unit);
- spu.texture[unit].start = texture->start;
- spu.texture[unit].width = width;
- spu.texture[unit].height = height;
+ for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
+ uint width = texture->width[i];
+ uint height = texture->height[i];
- spu.texture[unit].width4 = spu_splats((float) width);
- spu.texture[unit].height4 = spu_splats((float) height);
+ DEBUG_PRINTF(" LEVEL %u: at %p size[0] %u x %u\n", i,
+ texture->start[i], texture->width[i], texture->height[i]);
- spu.texture[unit].tiles_per_row = width / TILE_SIZE;
+ spu.texture[unit].level[i].start = texture->start[i];
+ spu.texture[unit].level[i].width = width;
+ spu.texture[unit].level[i].height = height;
- spu.texture[unit].tex_size_x_mask = spu_splats(width - 1);
- spu.texture[unit].tex_size_y_mask = spu_splats(height - 1);
+ spu.texture[unit].level[i].tiles_per_row = width / 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);
+ }
}
diff --git a/src/gallium/drivers/cell/spu/spu_funcs.c b/src/gallium/drivers/cell/spu/spu_funcs.c
index 4c90b701ee..f2946010bd 100644
--- a/src/gallium/drivers/cell/spu/spu_funcs.c
+++ b/src/gallium/drivers/cell/spu/spu_funcs.c
@@ -100,6 +100,7 @@ spu_log2(vector float x)
return spu_mul(v, k);
}
+
static struct vec_4x4
spu_txp(vector float s, vector float t, vector float r, vector float q,
unsigned unit)
diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h
index e3960dbe8b..9515543efe 100644
--- a/src/gallium/drivers/cell/spu/spu_main.h
+++ b/src/gallium/drivers/cell/spu/spu_main.h
@@ -107,7 +107,7 @@ struct spu_framebuffer
} ALIGN16_ATTRIB;
-struct spu_texture
+struct spu_texture_level
{
void *start;
ushort width, height;
@@ -118,6 +118,11 @@ struct spu_texture
vector unsigned int tex_size_y_mask; /**< splat(height-1) */
} ALIGN16_ATTRIB;
+struct spu_texture
+{
+ struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
+} ALIGN16_ATTRIB;
+
/**
* All SPU global/context state will be in a singleton object of this type:
diff --git a/src/gallium/drivers/cell/spu/spu_texture.c b/src/gallium/drivers/cell/spu/spu_texture.c
index 96ef88822a..96c09e3ccb 100644
--- a/src/gallium/drivers/cell/spu/spu_texture.c
+++ b/src/gallium/drivers/cell/spu/spu_texture.c
@@ -27,6 +27,7 @@
#include <transpose_matrix4x4.h>
+#include <math.h>
#include "pipe/p_compiler.h"
#include "spu_main.h"
@@ -42,11 +43,12 @@
void
invalidate_tex_cache(void)
{
+ uint lvl = 0;
uint unit = 0;
- uint bytes = 4 * spu.texture[unit].width
- * spu.texture[unit].height;
+ uint bytes = 4 * spu.texture[unit].level[lvl].width
+ * spu.texture[unit].level[lvl].height;
- spu_dcache_mark_dirty((unsigned) spu.texture[unit].start, bytes);
+ spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
}
@@ -64,15 +66,17 @@ invalidate_tex_cache(void)
* a time.
*/
static void
-get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels)
+get_four_texels(uint unit, uint level, vec_uint4 x, vec_uint4 y,
+ vec_uint4 *texels)
{
- const unsigned texture_ea = (uintptr_t) spu.texture[unit].start;
+ 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 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 */
- const qword tiles_per_row = (qword) spu_splats(spu.texture[unit].tiles_per_row);
+ const qword tiles_per_row = (qword) spu_splats(tlevel->tiles_per_row);
const qword tile_size = (qword) spu_splats((unsigned) sizeof(tile_t));
qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x);
@@ -104,17 +108,18 @@ sample_texture4_nearest(vector float s, vector float t,
vector float r, vector float q,
uint unit, vector float colors[4])
{
- vector float ss = spu_mul(s, spu.texture[unit].width4);
- vector float tt = spu_mul(t, spu.texture[unit].height4);
+ 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 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].tex_size_x_mask);
- it = spu_and(it, spu.texture[unit].tex_size_y_mask);
+ 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);
- get_four_texels(unit, is, it, texels);
+ get_four_texels(unit, lvl, is, it, texels);
/* convert four packed ARGBA pixels to float RRRR,GGGG,BBBB,AAAA */
spu_unpack_A8R8G8B8_transpose4(texels, colors);
@@ -130,8 +135,9 @@ sample_texture4_bilinear(vector float s, vector float t,
vector float r, vector float q,
uint unit, vector float colors[4])
{
- vector float ss = spu_madd(s, spu.texture[unit].width4, spu_splats(-0.5f));
- vector float tt = spu_madd(t, spu.texture[unit].height4, spu_splats(-0.5f));
+ 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 unsigned int is0 = spu_convtu(ss, 0);
vector unsigned int it0 = spu_convtu(tt, 0);
@@ -141,17 +147,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].tex_size_x_mask);
- it0 = spu_and(it0, spu.texture[unit].tex_size_y_mask);
- is1 = spu_and(is1, spu.texture[unit].tex_size_x_mask);
- it1 = spu_and(it1, spu.texture[unit].tex_size_y_mask);
+ 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);
/* get packed int texels */
vector unsigned int texels[16];
- get_four_texels(unit, is0, it0, texels + 0); /* upper-left */
- get_four_texels(unit, is1, it0, texels + 4); /* upper-right */
- get_four_texels(unit, is0, it1, texels + 8); /* lower-left */
- get_four_texels(unit, is1, it1, texels + 12); /* lower-right */
+ 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 */
/* XXX possibly rework following code to compute the weighted sample
* colors with integer arithmetic for fewer int->float conversions.
@@ -270,10 +276,11 @@ sample_texture4_bilinear_2(vector float s, vector float t,
vector float r, vector float q,
uint unit, 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].width4, half);
- vector float tt = spu_madd(t, spu.texture[unit].height4, half);
+ 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);
/* convert float coords to fixed-pt coords with 8 fraction bits */
vector unsigned int is = spu_convtu(ss, 8);
@@ -294,17 +301,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].tex_size_x_mask);
- it0 = spu_and(it0, spu.texture[unit].tex_size_y_mask);
- is1 = spu_and(is1, spu.texture[unit].tex_size_x_mask);
- it1 = spu_and(it1, spu.texture[unit].tex_size_y_mask);
+ 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);
/* get packed int texels */
vector unsigned int texels[16];
- get_four_texels(unit, is0, it0, texels + 0); /* upper-left */
- get_four_texels(unit, is1, it0, texels + 4); /* upper-right */
- get_four_texels(unit, is0, it1, texels + 8); /* lower-left */
- get_four_texels(unit, is1, it1, texels + 12); /* lower-right */
+ 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 */
/* twiddle packed 32-bit BGRA pixels into RGBA as four unsigned ints */
{
@@ -363,3 +370,54 @@ sample_texture4_bilinear_2(vector float s, vector float t,
cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
colors[3] = spu_convtf(cSum, 24);
}
+
+
+
+/**
+ * Compute level of detail factor from texcoords.
+ */
+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;
+ 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));
+ float dtdy = height * (spu_extract(t, 2) - spu_extract(t, 0));
+ float x = dsdx * dsdx + dtdx * dtdx;
+ float y = dsdy * dsdy + dtdy * dtdy;
+ float rho = x > y ? x : y;
+ rho = sqrtf(rho);
+ float lambda = logf(rho) * 1.442695f;
+ return lambda;
+}
+
+
+
+/**
+ * Texture sampling with level of detail selection.
+ */
+void
+sample_texture4_lod(vector float s, vector float t,
+ vector float r, vector float q,
+ uint unit, vector float colors[4])
+{
+ float lambda = compute_lambda(unit, s, t);
+
+ 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;
+
+ /*
+ sample_texture4_bilinear_2(s, t, r, q, unit, level, colors);
+ */
+}
+
diff --git a/src/gallium/drivers/cell/spu/spu_texture.h b/src/gallium/drivers/cell/spu/spu_texture.h
index 38a17deda2..4802f7c47c 100644
--- a/src/gallium/drivers/cell/spu/spu_texture.h
+++ b/src/gallium/drivers/cell/spu/spu_texture.h
@@ -53,4 +53,10 @@ sample_texture4_bilinear_2(vector float s, vector float t,
uint unit, 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]);
+
+
#endif /* SPU_TEXTURE_H */