Merge branch 'tex-tilecache' into softpipe-opt
authorKeith Whitwell <keithw@vmware.com>
Sun, 23 Aug 2009 09:23:46 +0000 (10:23 +0100)
committerKeith Whitwell <keithw@vmware.com>
Sun, 23 Aug 2009 09:23:46 +0000 (10:23 +0100)
Conflicts:
src/gallium/drivers/softpipe/sp_state_derived.c
src/gallium/drivers/softpipe/sp_state_sampler.c
src/gallium/drivers/softpipe/sp_tex_sample.c
src/gallium/drivers/softpipe/sp_tex_sample.h
src/gallium/drivers/softpipe/sp_tile_cache.c

1  2 
src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_state_derived.c
src/gallium/drivers/softpipe/sp_state_sampler.c
src/gallium/drivers/softpipe/sp_tex_sample.c
src/gallium/drivers/softpipe/sp_tex_sample.h
src/gallium/drivers/softpipe/sp_tex_tile_cache.c
src/gallium/drivers/softpipe/sp_tile_cache.c
src/gallium/drivers/softpipe/sp_tile_cache.h

@@@ -34,8 -34,6 +34,8 @@@
  #include "sp_context.h"
  #include "sp_screen.h"
  #include "sp_state.h"
- #include "sp_tile_cache.h"
 +#include "sp_texture.h"
++#include "sp_tex_tile_cache.h"
  
  
  /**
@@@ -200,18 -198,21 +200,18 @@@ update_tgsi_samplers( struct softpipe_c
  {
     unsigned i;
  
 -   /* vertex shader samplers */
 -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
 -      softpipe->tgsi.vert_samplers[i].sampler = softpipe->sampler[i];
 -      softpipe->tgsi.vert_samplers[i].texture = softpipe->texture[i];
 -   }
 -
 -   /* fragment shader samplers */
 -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
 -      softpipe->tgsi.frag_samplers[i].sampler = softpipe->sampler[i];
 -      softpipe->tgsi.frag_samplers[i].texture = softpipe->texture[i];
 -      softpipe->tgsi.frag_samplers[i].base.get_samples = sp_get_samples_fragment;
 -   }
 +   softpipe_reset_sampler_varients( softpipe );
  
     for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
-       struct softpipe_tile_cache *tc = softpipe->tex_cache[i];
 -      sp_tex_tile_cache_validate_texture( softpipe->tex_cache[i] );
++      struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[i];
 +      if (tc->texture) {
 +         struct softpipe_texture *spt = softpipe_texture(tc->texture);
 +         if (spt->timestamp != tc->timestamp) {
-             sp_tile_cache_validate_texture( tc );
++          sp_tex_tile_cache_validate_texture( tc );
 +            _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
 +            tc->timestamp = spt->timestamp;
 +         }
 +      }
     }
  }
  
  #include "util/u_memory.h"
  
  #include "draw/draw_context.h"
 +#include "draw/draw_context.h"
  
  #include "sp_context.h"
 -#include "sp_context.h"
  #include "sp_state.h"
  #include "sp_texture.h"
- #include "sp_tile_cache.h"
 +#include "sp_tex_sample.h"
+ #include "sp_tex_tile_cache.h"
 -#include "draw/draw_context.h"
  
  
 +struct sp_sampler {
 +   struct pipe_sampler_state base;
 +   struct sp_sampler_varient *varients;
 +   struct sp_sampler_varient *current;
 +};
 +
 +static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler )
 +{
 +   return (struct sp_sampler *)sampler;
 +}
 +
  
  void *
  softpipe_create_sampler_state(struct pipe_context *pipe,
   *
   * Authors:
   *   Brian Paul
 + *   Keith Whitwell
   */
  
 -#include "sp_context.h"
 -#include "sp_quad.h"
 -#include "sp_surface.h"
 -#include "sp_texture.h"
 -#include "sp_tex_sample.h"
 -#include "sp_tex_tile_cache.h"
  #include "pipe/p_context.h"
  #include "pipe/p_defines.h"
 +#include "pipe/p_shader_tokens.h"
  #include "util/u_math.h"
  #include "util/u_memory.h"
- #include "sp_tile_cache.h"
 +#include "sp_quad.h"   /* only for #define QUAD_* tokens */
 +#include "sp_tex_sample.h"
++#include "sp_tex_tile_cache.h"
  
  
  
@@@ -600,19 -659,19 +600,19 @@@ compute_lambda_vert(const struct sp_sam
   * \param rgba  the quad to put the texel/color into
   * \param j  which element of the rgba quad to write to
   *
-  * XXX maybe move this into sp_tile_cache.c and merge with the
+  * XXX maybe move this into sp_tex_tile_cache.c and merge with the
   * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...
   */
 -static void
 +static INLINE void
  get_texel_quad_2d(const struct tgsi_sampler *tgsi_sampler,
                    unsigned face, unsigned level, int x, int y, 
                    const float *out[4])
  {
 -   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
 +   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
  
-    const struct softpipe_cached_tile *tile
+    const struct softpipe_tex_cached_tile *tile
        = sp_get_cached_tile_tex(samp->cache,
-                                tile_address(x, y, 0, face, level));
+                                tex_tile_address(x, y, 0, face, level));
  
     y %= TILE_SIZE;
     x %= TILE_SIZE;
@@@ -627,11 -686,11 +627,11 @@@ static INLINE const float 
  get_texel_2d_ptr(const struct tgsi_sampler *tgsi_sampler,
                   unsigned face, unsigned level, int x, int y)
  {
 -   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
 +   const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler);
  
-    const struct softpipe_cached_tile *tile
+    const struct softpipe_tex_cached_tile *tile
        = sp_get_cached_tile_tex(samp->cache,
-                                tile_address(x, y, 0, face, level));
+                                tex_tile_address(x, y, 0, face, level));
  
     y %= TILE_SIZE;
     x %= TILE_SIZE;
@@@ -1543,130 -1593,16 +1543,130 @@@ static filter_func get_img_filter( cons
  
  
  /**
 - * Called via tgsi_sampler::get_samples() when running a vertex shader.
 - * Get four filtered RGBA values from the sampler's texture.
 + * Bind the given texture object and texture cache to the sampler varient.
   */
  void
 -sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler,
 -                      const float s[QUAD_SIZE],
 -                      const float t[QUAD_SIZE],
 -                      const float p[QUAD_SIZE],
 -                      float lodbias,
 -                      float rgba[NUM_CHANNELS][QUAD_SIZE])
 +sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp,
-                                  struct softpipe_tile_cache *tex_cache,
++                                 struct softpipe_tex_tile_cache *tex_cache,
 +                                 const struct pipe_texture *texture )
 +{
 +   const struct pipe_sampler_state *sampler = samp->sampler;
 +
 +   samp->texture = texture;
 +   samp->cache = tex_cache;
 +   samp->xpot = util_unsigned_logbase2( texture->width[0] );
 +   samp->ypot = util_unsigned_logbase2( texture->height[0] );
 +   samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level);
 +}
 +
 +
 +void
 +sp_sampler_varient_destroy( struct sp_sampler_varient *samp )
  {
 -   sp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba);
 +   FREE(samp);
 +}
 +
 +
 +/* Create a sampler varient for a given set of non-orthogonal state.  Currently the 
 + */
 +struct sp_sampler_varient *
 +sp_create_sampler_varient( const struct pipe_sampler_state *sampler,
 +                           const union sp_sampler_key key )
 +{
 +   struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient);
 +   if (!samp)
 +      return NULL;
 +
 +   samp->sampler = sampler;
 +   samp->key = key;
 +
 +   /* Note that (for instance) linear_texcoord_s and
 +    * nearest_texcoord_s may be active at the same time, if the
 +    * sampler min_img_filter differs from its mag_img_filter.
 +    */
 +   if (sampler->normalized_coords) {
 +      samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
 +      samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
 +      samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
 +      
 +      samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
 +      samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
 +      samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
 +   }
 +   else {
 +      samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
 +      samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
 +      samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
 +      
 +      samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
 +      samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
 +      samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
 +   }
 +   
 +   samp->compute_lambda = get_lambda_func( key );
 +
 +   samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler);
 +   samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler);
 +
 +   switch (sampler->min_mip_filter) {
 +   case PIPE_TEX_MIPFILTER_NONE:
 +      if (sampler->min_img_filter == sampler->mag_img_filter) 
 +         samp->mip_filter = samp->min_img_filter;         
 +      else
 +         samp->mip_filter = mip_filter_none;
 +      break;
 +
 +   case PIPE_TEX_MIPFILTER_NEAREST:
 +      samp->mip_filter = mip_filter_nearest;
 +      break;
 +
 +   case PIPE_TEX_MIPFILTER_LINEAR:
 +      if (key.bits.is_pot &&
 +          sampler->min_img_filter == sampler->mag_img_filter &&
 +          sampler->normalized_coords &&
 +          sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
 +          sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
 +          sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR)
 +      {
 +         samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT;
 +      }
 +      else 
 +      {
 +         samp->mip_filter = mip_filter_linear;
 +      }
 +      break;
 +   }
 +
 +   if (sampler->compare_mode != FALSE) {
 +      samp->compare = sample_compare;
 +   }
 +   else {
 +      /* Skip compare operation by promoting the mip_filter function
 +       * pointer:
 +       */
 +      samp->compare = samp->mip_filter;
 +   }
 +   
 +   if (key.bits.target == PIPE_TEXTURE_CUBE) {
 +      samp->base.get_samples = sample_cube;
 +   }
 +   else {
 +      samp->faces[0] = 0;
 +      samp->faces[1] = 0;
 +      samp->faces[2] = 0;
 +      samp->faces[3] = 0;
 +
 +      /* Skip cube face determination by promoting the compare
 +       * function pointer:
 +       */
 +      samp->base.get_samples = samp->compare;
 +   }
 +
 +   return samp;
  }
 +
 +
 +
 +
 +
 +
@@@ -75,78 -39,42 +75,78 @@@ struct sp_sampler_varien
  {
     struct tgsi_sampler base;  /**< base class */
  
-    struct softpipe_tile_cache *cache;
 +   union sp_sampler_key key;
 +
 +   /* The owner of this struct:
 +    */
 +   const struct pipe_sampler_state *sampler;
 +
 +
 +   /* Currently bound texture:
 +    */
 +   const struct pipe_texture *texture;
++   struct softpipe_tex_tile_cache *cache;
 +
 +   unsigned processor;
 +
     /* For sp_get_samples_2d_linear_POT:
      */
     unsigned xpot;
     unsigned ypot;
     unsigned level;
  
 -   const struct pipe_texture *texture;
 -   const struct pipe_sampler_state *sampler;
 +   unsigned faces[4];
 +   
 +   wrap_nearest_func nearest_texcoord_s;
 +   wrap_nearest_func nearest_texcoord_t;
 +   wrap_nearest_func nearest_texcoord_p;
  
 -   struct softpipe_tex_tile_cache *cache;
 +   wrap_linear_func linear_texcoord_s;
 +   wrap_linear_func linear_texcoord_t;
 +   wrap_linear_func linear_texcoord_p;
 +
 +   filter_func min_img_filter;
 +   filter_func mag_img_filter;
 +
 +   compute_lambda_func compute_lambda;
 +
 +   filter_func mip_filter;
 +   filter_func compare;
 +   
 +   /* Linked list:
 +    */
 +   struct sp_sampler_varient *next;
  };
  
 +struct sp_sampler;
  
 +/* Create a sampler varient for a given set of non-orthogonal state.  Currently the 
 + */
 +struct sp_sampler_varient *
 +sp_create_sampler_varient( const struct pipe_sampler_state *sampler,
 +                           const union sp_sampler_key key );
  
 -static INLINE struct sp_shader_sampler *
 -sp_shader_sampler(const struct tgsi_sampler *sampler)
 -{
 -   return (struct sp_shader_sampler *) sampler;
 -}
 +void sp_sampler_varient_bind_texture( struct sp_sampler_varient *varient,
-                                       struct softpipe_tile_cache *tex_cache,
++                                      struct softpipe_tex_tile_cache *tex_cache,
 +                                      const struct pipe_texture *tex );
  
 +void sp_sampler_varient_destroy( struct sp_sampler_varient * );
  
 -extern void
 -sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler,
 -                        const float s[QUAD_SIZE],
 -                        const float t[QUAD_SIZE],
 -                        const float p[QUAD_SIZE],
 -                        float lodbias,
 -                        float rgba[NUM_CHANNELS][QUAD_SIZE]);
 +
 +
 +static INLINE struct sp_sampler_varient *
 +sp_sampler_varient(const struct tgsi_sampler *sampler)
 +{
 +   return (struct sp_sampler_varient *) sampler;
 +}
  
  extern void
 -sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler,
 -                      const float s[QUAD_SIZE],
 -                      const float t[QUAD_SIZE],
 -                      const float p[QUAD_SIZE],
 -                      float lodbias,
 -                      float rgba[NUM_CHANNELS][QUAD_SIZE]);
 +sp_get_samples(struct tgsi_sampler *tgsi_sampler,
 +               const float s[QUAD_SIZE],
 +               const float t[QUAD_SIZE],
 +               const float p[QUAD_SIZE],
 +               float lodbias,
 +               float rgba[NUM_CHANNELS][QUAD_SIZE]);
  
  
  #endif /* SP_TEX_SAMPLE_H */
index 0000000,c2dd68c..407a22a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,274 +1,273 @@@
 -   if (tc->texture) {
 -      struct softpipe_texture *spt = softpipe_texture(tc->texture);
 -      if (spt->timestamp != tc->timestamp) {
 -         /* texture was modified, invalidate all cached tiles */
 -         uint i;
 -         _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
 -         for (i = 0; i < NUM_ENTRIES; i++) {
 -            tc->entries[i].addr.bits.invalid = 1;
 -         }
 -
 -         tc->timestamp = spt->timestamp;
 -      }
+ /**************************************************************************
+  * 
+  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+  * All Rights Reserved.
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the
+  * "Software"), to deal in the Software without restriction, including
+  * without limitation the rights to use, copy, modify, merge, publish,
+  * distribute, sub license, and/or sell copies of the Software, and to
+  * permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice (including the
+  * next paragraph) shall be included in all copies or substantial portions
+  * of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+  * 
+  **************************************************************************/
+ /**
+  * Texture tile caching.
+  *
+  * Author:
+  *    Brian Paul
+  */
+ #include "pipe/p_inlines.h"
+ #include "util/u_memory.h"
+ #include "util/u_tile.h"
+ #include "sp_context.h"
+ #include "sp_surface.h"
+ #include "sp_texture.h"
+ #include "sp_tex_tile_cache.h"
+    
+ struct softpipe_tex_tile_cache *
+ sp_create_tex_tile_cache( struct pipe_screen *screen )
+ {
+    struct softpipe_tex_tile_cache *tc;
+    uint pos;
+    tc = CALLOC_STRUCT( softpipe_tex_tile_cache );
+    if (tc) {
+       tc->screen = screen;
+       for (pos = 0; pos < NUM_ENTRIES; pos++) {
+          tc->entries[pos].addr.bits.invalid = 1;
+       }
+       tc->last_tile = &tc->entries[0]; /* any tile */
+    }
+    return tc;
+ }
+ void
+ sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
+ {
+    struct pipe_screen *screen;
+    uint pos;
+    for (pos = 0; pos < NUM_ENTRIES; pos++) {
+       /*assert(tc->entries[pos].x < 0);*/
+    }
+    if (tc->transfer) {
+       screen = tc->transfer->texture->screen;
+       screen->tex_transfer_destroy(tc->transfer);
+    }
+    if (tc->tex_trans) {
+       screen = tc->tex_trans->texture->screen;
+       screen->tex_transfer_destroy(tc->tex_trans);
+    }
+    FREE( tc );
+ }
+ void
+ sp_tex_tile_cache_map_transfers(struct softpipe_tex_tile_cache *tc)
+ {
+    if (tc->tex_trans && !tc->tex_trans_map)
+       tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
+ }
+ void
+ sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache *tc)
+ {
+    if (tc->tex_trans_map) {
+       tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+       tc->tex_trans_map = NULL;
+    }
+ }
++/**
++ * Invalidate all cached tiles for the cached texture.
++ * Should be called when the texture is modified.
++ */
+ void
+ sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc)
+ {
++   unsigned i;
++
++   assert(tc);
++   assert(tc->texture);
++
++   for (i = 0; i < NUM_ENTRIES; i++) {
++      tc->entries[i].addr.bits.invalid = 1;
+    }
+ }
+ /**
+  * Specify the texture to cache.
+  */
+ void
+ sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc,
+                           struct pipe_texture *texture)
+ {
+    uint i;
+    assert(!tc->transfer);
+    if (tc->texture != texture) {
+       pipe_texture_reference(&tc->texture, texture);
+       if (tc->tex_trans) {
+          struct pipe_screen *screen = tc->tex_trans->texture->screen;
+          
+          if (tc->tex_trans_map) {
+             screen->transfer_unmap(screen, tc->tex_trans);
+             tc->tex_trans_map = NULL;
+          }
+          screen->tex_transfer_destroy(tc->tex_trans);
+          tc->tex_trans = NULL;
+       }
+       /* mark as entries as invalid/empty */
+       /* XXX we should try to avoid this when the teximage hasn't changed */
+       for (i = 0; i < NUM_ENTRIES; i++) {
+          tc->entries[i].addr.bits.invalid = 1;
+       }
+       tc->tex_face = -1; /* any invalid value here */
+    }
+ }
+ /**
+  * Flush the tile cache: write all dirty tiles back to the transfer.
+  * any tiles "flagged" as cleared will be "really" cleared.
+  */
+ void
+ sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
+ {
+    int pos;
+    if (tc->texture) {
+       /* caching a texture, mark all entries as empty */
+       for (pos = 0; pos < NUM_ENTRIES; pos++) {
+          tc->entries[pos].addr.bits.invalid = 1;
+       }
+       tc->tex_face = -1;
+    }
+ }
+ /**
+  * Given the texture face, level, zslice, x and y values, compute
+  * the cache entry position/index where we'd hope to find the
+  * cached texture tile.
+  * This is basically a direct-map cache.
+  * XXX There's probably lots of ways in which we can improve this.
+  */
+ static INLINE uint
+ tex_cache_pos( union tex_tile_address addr )
+ {
+    uint entry = (addr.bits.x + 
+                  addr.bits.y * 9 + 
+                  addr.bits.z * 3 + 
+                  addr.bits.face + 
+                  addr.bits.level * 7);
+    return entry % NUM_ENTRIES;
+ }
+ /**
+  * Similar to sp_get_cached_tile() but for textures.
+  * Tiles are read-only and indexed with more params.
+  */
+ const struct softpipe_tex_cached_tile *
+ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, 
+                         union tex_tile_address addr )
+ {
+    struct pipe_screen *screen = tc->screen;
+    struct softpipe_tex_cached_tile *tile;
+    
+    tile = tc->entries + tex_cache_pos( addr );
+    if (addr.value != tile->addr.value) {
+       /* cache miss.  Most misses are because we've invaldiated the
+        * texture cache previously -- most commonly on binding a new
+        * texture.  Currently we effectively flush the cache on texture
+        * bind.
+        */
+ #if 0
+       _debug_printf("miss at %u:  x=%d y=%d z=%d face=%d level=%d\n"
+                     "   tile %u:  x=%d y=%d z=%d face=%d level=%d\n",
+                     pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
+                     pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
+ #endif
+       /* check if we need to get a new transfer */
+       if (!tc->tex_trans ||
+           tc->tex_face != addr.bits.face ||
+           tc->tex_level != addr.bits.level ||
+           tc->tex_z != addr.bits.z) {
+          /* get new transfer (view into texture) */
+          if (tc->tex_trans) {
+             if (tc->tex_trans_map) {
+                tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+                tc->tex_trans_map = NULL;
+             }
+             screen->tex_transfer_destroy(tc->tex_trans);
+             tc->tex_trans = NULL;
+          }
+          tc->tex_trans = 
+             screen->get_tex_transfer(screen, tc->texture, 
+                                      addr.bits.face, 
+                                      addr.bits.level, 
+                                      addr.bits.z, 
+                                      PIPE_TRANSFER_READ, 0, 0,
+                                      tc->texture->width[addr.bits.level],
+                                      tc->texture->height[addr.bits.level]);
+          tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
+          tc->tex_face = addr.bits.face;
+          tc->tex_level = addr.bits.level;
+          tc->tex_z = addr.bits.z;
+       }
+       /* get tile from the transfer (view into texture) */
+       pipe_get_tile_rgba(tc->tex_trans,
+                          addr.bits.x * TILE_SIZE, 
+                          addr.bits.y * TILE_SIZE,
+                          TILE_SIZE, TILE_SIZE,
+                          (float *) tile->data.color);
+       tile->addr = addr;
+    }
+    tc->last_tile = tile;
+    return tile;
+ }
@@@ -190,69 -183,8 +181,9 @@@ sp_tile_cache_unmap_transfers(struct so
        tc->screen->transfer_unmap(tc->screen, tc->transfer);
        tc->transfer_map = NULL;
     }
-    if (tc->tex_trans_map) {
-       tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
-       tc->tex_trans_map = NULL;
-    }
- }
- /**
-  * Invalidate all cached tiles for the cached texture.
-  * Should be called when the texture is modified.
-  */
- void
- sp_tile_cache_validate_texture(struct softpipe_tile_cache *tc)
- {
-    uint i;
-    assert(tc);
-    assert(tc->texture);
-    for (i = 0; i < NUM_ENTRIES; i++) {
-       tc->entries[i].addr.bits.invalid = 1;
-    }
- }
- /**
-  * Specify the texture to cache.
-  */
- void
- sp_tile_cache_set_texture(struct softpipe_tile_cache *tc,
-                           struct pipe_texture *texture)
- {
-    uint i;
-    assert(!tc->transfer);
-    if (tc->texture != texture) {
-       pipe_texture_reference(&tc->texture, texture);
-       if (tc->tex_trans) {
-          struct pipe_screen *screen = tc->tex_trans->texture->screen;
-          
-          if (tc->tex_trans_map) {
-             screen->transfer_unmap(screen, tc->tex_trans);
-             tc->tex_trans_map = NULL;
-          }
-          screen->tex_transfer_destroy(tc->tex_trans);
-          tc->tex_trans = NULL;
-       }
-       /* mark as entries as invalid/empty */
-       /* XXX we should try to avoid this when the teximage hasn't changed */
-       for (i = 0; i < NUM_ENTRIES; i++) {
-          tc->entries[i].addr.bits.invalid = 1;
-       }
-       tc->tex_face = -1; /* any invalid value here */
-    }
  }
  
 +
  /**
   * Set pixels in a tile to the given clear color/value, float.
   */