diff options
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/drivers/cell/common.h | 6 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/ppu/cell_screen.c | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/ppu/cell_state_emit.c | 18 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/ppu/cell_texture.c | 48 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/ppu/cell_texture.h | 6 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/spu/spu_command.c | 37 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/spu/spu_funcs.c | 1 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/spu/spu_main.h | 7 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/spu/spu_texture.c | 120 | ||||
| -rw-r--r-- | src/gallium/drivers/cell/spu/spu_texture.h | 6 | 
10 files changed, 176 insertions, 77 deletions
| diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index 5dc756023f..e4de9a551d 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -67,6 +67,7 @@  #define CELL_MAX_SPUS 6  #define CELL_MAX_SAMPLERS 4 +#define CELL_MAX_TEXTURE_LEVELS 12  /* 2k x 2k */  #define TILE_SIZE 32 @@ -251,8 +252,9 @@ struct cell_command_texture  {     uint64_t opcode;     /**< CELL_CMD_STATE_TEXTURE */     uint unit; -   void *start;         /**< Address in main memory */ -   ushort width, height; +   void *start[CELL_MAX_TEXTURE_LEVELS];   /**< Address in main memory */ +   ushort width[CELL_MAX_TEXTURE_LEVELS]; +   ushort height[CELL_MAX_TEXTURE_LEVELS];  }; diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index 47ba6fa290..d223557950 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -76,11 +76,11 @@ cell_get_param(struct pipe_screen *screen, int param)     case PIPE_CAP_TEXTURE_SHADOW_MAP:        return 10;     case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: -      return 12; /* max 2Kx2K */ +      return CELL_MAX_TEXTURE_LEVELS;     case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:        return 8;  /* max 128x128x128 */     case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: -      return 12; /* max 2Kx2K */ +      return CELL_MAX_TEXTURE_LEVELS;     default:        return 10;     } diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index cbfa393cfb..7090b4c99f 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -211,14 +211,20 @@ cell_emit_state(struct cell_context *cell)           texture->opcode = CELL_CMD_STATE_TEXTURE;           texture->unit = i;           if (cell->texture[i]) { -            texture->start = cell->texture[i]->tiled_data; -            texture->width = cell->texture[i]->base.width[0]; -            texture->height = cell->texture[i]->base.height[0]; +            uint level; +            for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { +               texture->start[level] = cell->texture[i]->tiled_data[level]; +               texture->width[level] = cell->texture[i]->base.width[level]; +               texture->height[level] = cell->texture[i]->base.height[level]; +            }           }           else { -            texture->start = NULL; -            texture->width = 1; -            texture->height = 1; +            uint level; +            for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { +               texture->start[level] = NULL; +               texture->width[level] = 1; +               texture->height[level] = 1; +            }           }        }     } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index b6590dfb86..f5f81ac3cc 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -66,6 +66,8 @@ cell_texture_layout(struct cell_texture * spt)        unsigned size;        unsigned w_tile, h_tile; +      assert(level < CELL_MAX_TEXTURE_LEVELS); +        /* width, height, rounded up to tile size */        w_tile = align(width, TILE_SIZE);        h_tile = align(height, TILE_SIZE); @@ -249,33 +251,41 @@ cell_tile_texture(struct cell_context *cell,                    struct cell_texture *texture)  {     struct pipe_screen *screen = cell->pipe.screen; -   uint face = 0, level = 0, zslice = 0; -   struct pipe_surface *surf; -   const uint w = texture->base.width[0], h = texture->base.height[0]; +   uint face = 0, level, zslice = 0;     const uint *src; -   /* temporary restrictions: */ -   assert(w >= TILE_SIZE); -   assert(h >= TILE_SIZE); -   assert(w % TILE_SIZE == 0); -   assert(h % TILE_SIZE == 0); +   for (level = 0; level <= texture->base.last_level; level++) { +      if (!texture->tiled_data[level]) { +         struct pipe_surface *surf; -   surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice, -                                  PIPE_BUFFER_USAGE_CPU_WRITE); -   ASSERT(surf); +         const uint w = texture->base.width[level], h = texture->base.height[level]; -   src = (const uint *) pipe_surface_map(surf, PIPE_BUFFER_USAGE_CPU_WRITE); +         if (w < 32 || h < 32) +            continue; +         /* temporary restrictions: */ +         assert(w >= TILE_SIZE); +         assert(h >= TILE_SIZE); +         assert(w % TILE_SIZE == 0); +         assert(h % TILE_SIZE == 0); -   if (texture->tiled_data) { -      align_free(texture->tiled_data); -   } -   texture->tiled_data = align_malloc(w * h * 4, 16); +         surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice, +                                        PIPE_BUFFER_USAGE_CPU_WRITE); +         ASSERT(surf); +          +         src = (const uint *) pipe_surface_map(surf, PIPE_BUFFER_USAGE_CPU_WRITE); -   tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src); +         if (texture->tiled_data[level]) { +            align_free(texture->tiled_data[level]); +         } +         texture->tiled_data[level] = align_malloc(w * h * 4, 16); -   pipe_surface_unmap(surf); +         tile_copy_data(w, h, TILE_SIZE, texture->tiled_data[level], src); -   pipe_surface_reference(&surf, NULL); +         pipe_surface_unmap(surf); + +         pipe_surface_reference(&surf, NULL); +      } +   }  } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index 6d37e95ebc..6d35736984 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -40,15 +40,15 @@ struct cell_texture  {     struct pipe_texture base; -   unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; -   unsigned long stride[PIPE_MAX_TEXTURE_LEVELS]; +   unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS]; +   unsigned long stride[CELL_MAX_TEXTURE_LEVELS];     /* The data is held here:      */     struct pipe_buffer *buffer;     unsigned long buffer_size; -   void *tiled_data;  /* XXX this may be temporary */ /*ALIGN16*/ +   void *tiled_data[CELL_MAX_TEXTURE_LEVELS];  /* XXX this may be temporary */ /*ALIGN16*/  }; 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 */ | 
