gallium: clean-up, simplification of mipmapped textures
authorBrian <brian.paul@tungstengraphics.com>
Tue, 12 Feb 2008 21:53:25 +0000 (14:53 -0700)
committerBen Skeggs <skeggsb@gmail.com>
Fri, 15 Feb 2008 02:51:11 +0000 (13:51 +1100)
Remove pipe_texture->first_level (always implicitly zero).  This means there's
never any unused mipmap levels at the top.
In the state tracker, we no longer re-layout mipmapped textures if the
MinLod/MaxLod texture parameters change.  It's up to the driver to obey the
pipe_sampler->min/max_lod clamps.

13 files changed:
src/mesa/pipe/i915simple/i915_state.c
src/mesa/pipe/i915simple/i915_state_sampler.c
src/mesa/pipe/i915simple/i915_texture.c
src/mesa/pipe/i965simple/brw_tex_layout.c
src/mesa/pipe/i965simple/brw_wm_surface_state.c
src/mesa/pipe/p_state.h
src/mesa/pipe/softpipe/sp_state_sampler.c
src/mesa/pipe/softpipe/sp_tex_sample.c
src/mesa/pipe/softpipe/sp_texture.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_gen_mipmap.c
src/mesa/state_tracker/st_texture.c
src/mesa/state_tracker/st_texture.h

index 950ea52..abd5571 100644 (file)
@@ -250,6 +250,13 @@ i915_create_sampler_state(struct pipe_context *pipe,
    if (sampler->normalized_coords)
       cso->state[1] |= SS3_NORMALIZED_COORDS;
 
+   if (0) /* XXX not tested yet */
+   {
+      int minlod = (int) (16.0 * sampler->min_lod);
+      minlod = CLAMP(minlod, 0, 16 * 11);
+      cso->state[1] |= (minlod << SS3_MIN_LOD_SHIFT);
+   }
+
    {
       ubyte r = float_to_ubyte(sampler->border_color[0]);
       ubyte g = float_to_ubyte(sampler->border_color[1]);
index 0dbbc52..9c1a5bb 100644 (file)
@@ -185,7 +185,7 @@ i915_update_texture(struct i915_context *i915, uint unit,
    const struct pipe_texture *pt = &tex->base;
    uint format, pitch;
    const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
-   const uint num_levels = pt->last_level - pt->first_level;
+   const uint num_levels = pt->last_level;
 
    assert(tex);
    assert(width);
index 6faeab1..6d37ae3 100644 (file)
@@ -118,11 +118,11 @@ i945_miptree_layout_2d( struct i915_texture *tex )
    tex->pitch = pt->width[0];
 
    /* May need to adjust pitch to accomodate the placement of
-    * the 2nd mipmap.  This occurs when the alignment
+    * the 2nd mipmap level.  This occurs when the alignment
     * constraints of mipmap placement push the right edge of the
-    * 2nd mipmap out past the width of its parent.
+    * 2nd mipmap level out past the width of its parent.
     */
-   if (pt->first_level != pt->last_level) {
+   if (pt->last_level > 0) {
       unsigned mip1_width = align_int(minify(pt->width[0]), align_w)
                        + minify(minify(pt->width[0]));
 
@@ -136,7 +136,7 @@ i945_miptree_layout_2d( struct i915_texture *tex )
    tex->pitch = align_int(tex->pitch * pt->cpp, 4) / pt->cpp;
    tex->total_height = 0;
 
-   for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
+   for (level = 0; level <= pt->last_level; level++) {
       unsigned img_height;
 
       i915_miptree_set_level_info(tex, level, 1, x, y, width, height, 1);
@@ -152,9 +152,9 @@ i945_miptree_layout_2d( struct i915_texture *tex )
        */
       tex->total_height = MAX2(tex->total_height, y + img_height);
 
-      /* Layout_below: step right after second mipmap.
+      /* Layout_below: step right after second mipmap level.
        */
-      if (level == pt->first_level + 1) {
+      if (level == 1) {
         x += align_int(width, align_w);
       }
       else {
@@ -204,7 +204,7 @@ i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
          tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
          tex->total_height = dim * 4;
 
-         for (level = pt->first_level; level <= pt->last_level; level++) {
+         for (level = 0; level <= pt->last_level; level++) {
             i915_miptree_set_level_info(tex, level, 6,
                                          0, 0,
                                          /*OLD: tex->pitch, tex->total_height,*/
@@ -219,7 +219,7 @@ i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
             unsigned y = initial_offsets[face][1] * dim;
             unsigned d = dim;
 
-            for (level = pt->first_level; level <= pt->last_level; level++) {
+            for (level = 0; level <= pt->last_level; level++) {
                i915_miptree_set_image_offset(tex, level, face, x, y);
                d >>= 1;
                x += step_offsets[face][0] * d;
@@ -240,7 +240,7 @@ i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
 
          /* XXX: hardware expects/requires 9 levels at minimum.
           */
-         for (level = pt->first_level; level <= MAX2(8, pt->last_level);
+         for (level = 0; level <= MAX2(8, pt->last_level);
               level++) {
             i915_miptree_set_level_info(tex, level, depth, 0, tex->total_height,
                                          width, height, depth);
@@ -256,7 +256,7 @@ i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
          /* Fixup depth image_offsets: 
           */
          depth = pt->depth[0];
-         for (level = pt->first_level; level <= pt->last_level; level++) {
+         for (level = 0; level <= pt->last_level; level++) {
             unsigned i;
             for (i = 0; i < depth; i++) 
                i915_miptree_set_image_offset(tex, level, i,
@@ -282,7 +282,7 @@ i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
          tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
          tex->total_height = 0;
 
-         for (level = pt->first_level; level <= pt->last_level; level++) {
+         for (level = 0; level <= pt->last_level; level++) {
             i915_miptree_set_level_info(tex, level, 1,
                                          0, tex->total_height,
                                          width, height, 1);
@@ -337,7 +337,7 @@ i945_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
 
          /* Set all the levels to effectively occupy the whole rectangular region. 
           */
-         for (level = pt->first_level; level <= pt->last_level; level++) {
+         for (level = 0; level <= pt->last_level; level++) {
             i915_miptree_set_level_info(tex, level, 6,
                                          0, 0,
                                          lvlWidth, lvlHeight, 1);
@@ -355,12 +355,12 @@ i945_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
                y = tex->total_height - 4;
                x = (face - 4) * 8;
             }
-            else if (dim < 4 && (face > 0 || pt->first_level > 0)) {
+            else if (dim < 4 && (face > 0)) {
                y = tex->total_height - 4;
                x = face * 8;
             }
 
-            for (level = pt->first_level; level <= pt->last_level; level++) {
+            for (level = 0; level <= pt->last_level; level++) {
                i915_miptree_set_image_offset(tex, level, face, x, y);
 
                d >>= 1;
@@ -418,7 +418,7 @@ i945_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
          pack_x_pitch = tex->pitch;
          pack_x_nr = 1;
 
-         for (level = pt->first_level; level <= pt->last_level; level++) {
+         for (level = 0; level <= pt->last_level; level++) {
             unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
             int x = 0;
             int y = 0;
index 405fd1f..90561f1 100644 (file)
@@ -146,7 +146,7 @@ static void i945_miptree_layout_2d(struct brw_texture *tex)
     * constraints of mipmap placement push the right edge of the
     * 2nd mipmap out past the width of its parent.
     */
-   if (pt->first_level != pt->last_level) {
+   if (pt->last_level > 0) {
       unsigned mip1_width;
 
       if (pt->compressed) {
@@ -168,7 +168,7 @@ static void i945_miptree_layout_2d(struct brw_texture *tex)
    tex->pitch = align(tex->pitch * pt->cpp, 4) / pt->cpp;
    tex->total_height = 0;
 
-   for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
+   for (level = 0; level <= pt->last_level; level++) {
       unsigned img_height;
 
       intel_miptree_set_level_info(tex, level, 1, x, y, width,
@@ -187,7 +187,7 @@ static void i945_miptree_layout_2d(struct brw_texture *tex)
 
       /* Layout_below: step right after second mipmap.
        */
-      if (level == pt->first_level + 1) {
+      if (level == 1) {
         x += align(width, align_w);
       }
       else {
@@ -234,7 +234,7 @@ static boolean brw_miptree_layout(struct pipe_context *pipe, struct brw_texture
       pack_x_pitch = tex->pitch;
       pack_x_nr = 1;
 
-      for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
+      for (level = 0; level <= pt->last_level; level++) {
         unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
         int x = 0;
         int y = 0;
index cbb4f2e..d16d919 100644 (file)
@@ -154,7 +154,7 @@ void brw_update_texture_surface( struct brw_context *brw,
    /* Updated in emit_reloc */
    surf.ss1.base_addr = brw_buffer_offset( brw, tObj->buffer );
 
-   surf.ss2.mip_count = tObj->base.last_level - tObj->base.first_level;
+   surf.ss2.mip_count = tObj->base.last_level;
    surf.ss2.width = tObj->base.width[0] - 1;
    surf.ss2.height = tObj->base.height[0] - 1;
 
index 83ca43f..4d3a6b2 100644 (file)
@@ -234,14 +234,9 @@ struct pipe_sampler_state
    unsigned compare_mode:1;  /**< PIPE_TEX_COMPARE_x */
    unsigned compare_func:3;  /**< PIPE_FUNC_x */
    unsigned normalized_coords:1;  /**< Are coords normalized to [0,1]? */
-   float shadow_ambient; /**< shadow test fail color/intensity */
-   float min_lod;
-   float max_lod;
-   float lod_bias;
-#if 0 /* need these? */
-   int BaseLevel;     /**< min mipmap level, OpenGL 1.2 */
-   int MaxLevel;      /**< max mipmap level, OpenGL 1.2 */
-#endif
+   float shadow_ambient;          /**< shadow test fail color/intensity */
+   float lod_bias;                /**< LOD/lambda bias */
+   float min_lod, max_lod;        /**< LOD clamp range, after bias */
    float border_color[4];
    float max_anisotropy;
 };
@@ -277,8 +272,7 @@ struct pipe_texture
    enum pipe_texture_target target; /**< PIPE_TEXTURE_x */
    enum pipe_format format;         /**< PIPE_FORMAT_x */
 
-   unsigned first_level;
-   unsigned last_level;
+   unsigned last_level;    /**< Index of last mipmap level present/defined */
 
    unsigned width[PIPE_MAX_TEXTURE_LEVELS];
    unsigned height[PIPE_MAX_TEXTURE_LEVELS];
index 291bbc4..6a5a643 100644 (file)
@@ -34,6 +34,8 @@
 #include "sp_state.h"
 #include "sp_texture.h"
 #include "sp_tile_cache.h"
+#include "pipe/draw/draw_context.h"
+
 
 
 void *
@@ -73,6 +75,8 @@ softpipe_set_sampler_texture(struct pipe_context *pipe,
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
+   draw_flush(softpipe->draw);
+
    assert(unit < PIPE_MAX_SAMPLERS);
    softpipe->texture[unit] = softpipe_texture(texture);  /* ptr, not struct */
 
index 5e215c4..325bdb8 100644 (file)
@@ -449,7 +449,6 @@ compute_lambda(struct tgsi_sampler *sampler,
    }
 
    lambda = LOG2(rho);
-
    lambda += lodbias + sampler->state->lod_bias;
    lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
 
@@ -457,7 +456,6 @@ compute_lambda(struct tgsi_sampler *sampler,
 }
 
 
-
 /**
  * Do several things here:
  * 1. Compute lambda from the texcoords, if needed
@@ -477,7 +475,7 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
    if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
       /* no mipmap selection needed */
       *imgFilter = sampler->state->mag_img_filter;
-      *level0 = *level1 = sampler->texture->first_level;
+      *level0 = *level1 = (int) sampler->state->min_lod;
    }
    else {
       float lambda;
@@ -492,7 +490,7 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
       if (lambda < 0.0) { /* XXX threshold depends on the filter */
          /* magnifying */
          *imgFilter = sampler->state->mag_img_filter;
-         *level0 = *level1 = sampler->texture->first_level;
+         *level0 = *level1 = 0;
       }
       else {
          /* minifying */
@@ -503,19 +501,13 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
             /* Nearest mipmap level */
             const int lvl = (int) (lambda + 0.5);
             *level0 =
-            *level1 = CLAMP(lvl,
-                            (int) sampler->texture->first_level,
-                            (int) sampler->texture->last_level);
+            *level1 = CLAMP(lvl, 0, (int) sampler->texture->last_level);
          }
          else {
             /* Linear interpolation between mipmap levels */
             const int lvl = (int) lambda;
-            *level0 = CLAMP(lvl,
-                            (int) sampler->texture->first_level,
-                            (int) sampler->texture->last_level);
-            *level1 = CLAMP(lvl + 1,
-                            (int) sampler->texture->first_level,
-                            (int) sampler->texture->last_level);
+            *level0 = CLAMP(lvl,     0, (int) sampler->texture->last_level);
+            *level1 = CLAMP(lvl + 1, 0, (int) sampler->texture->last_level);
             *levelBlend = FRAC(lambda);  /* blending weight between levels */
          }
       }
index fd2cc3d..6de7a9b 100644 (file)
@@ -61,7 +61,7 @@ softpipe_texture_layout(struct softpipe_texture * spt)
 
    spt->buffer_size = 0;
 
-   for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
+   for (level = 0; level <= pt->last_level; level++) {
       pt->width[level] = width;
       pt->height[level] = height;
       pt->depth[level] = depth;
@@ -139,6 +139,8 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
    struct softpipe_texture *spt = softpipe_texture(pt);
    struct pipe_surface *ps;
 
+   assert(level <= pt->last_level);
+
    ps = pipe->winsys->surface_alloc(pipe->winsys);
    if (ps) {
       assert(ps->refcount);
index 7099ec3..f012b2f 100644 (file)
@@ -57,15 +57,10 @@ struct st_texture_object
 {
    struct gl_texture_object base;       /* The "parent" object */
 
-   /* The texture must include at least these levels once validated:
+   /* The texture must include at levels [0..lastLevel] once validated:
     */
-   GLuint firstLevel;
    GLuint lastLevel;
 
-   /* Offset for firstLevel image:
-    */
-   GLuint textureOffset;
-
    /* On validation any active images held in main memory or in other
     * textures will be copied to this texture and the old storage freed.
     */
@@ -585,12 +580,12 @@ st_TexImage(GLcontext * ctx,
       _mesa_align_free(texImage->Data);
    }
 
-   /* If this is the only texture image in the texture, could call
+   /* If this is the only mipmap level in the texture, could call
     * bmBufferData with NULL data to free the old block and avoid
     * waiting on any outstanding fences.
     */
    if (stObj->pt &&
-       stObj->pt->first_level == level &&
+       /*stObj->pt->first_level == level &&*/
        stObj->pt->last_level == level &&
        stObj->pt->target != PIPE_TEXTURE_CUBE &&
        !st_texture_match_image(stObj->pt, &stImage->base,
@@ -1363,13 +1358,8 @@ calculate_first_last_level(struct st_texture_object *stObj)
          firstLevel = lastLevel = tObj->BaseLevel;
       }
       else {
-         firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
-         firstLevel = MAX2(firstLevel, tObj->BaseLevel);
-         lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
-         lastLevel = MAX2(lastLevel, tObj->BaseLevel);
-         lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
-         lastLevel = MIN2(lastLevel, tObj->MaxLevel);
-         lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */
+         firstLevel = 0;
+         lastLevel = MIN2(tObj->MaxLevel - tObj->BaseLevel, baseImage->MaxLog2);
       }
       break;
    case GL_TEXTURE_RECTANGLE_NV:
@@ -1380,8 +1370,6 @@ calculate_first_last_level(struct st_texture_object *stObj)
       return;
    }
 
-   /* save these values */
-   stObj->firstLevel = firstLevel;
    stObj->lastLevel = lastLevel;
 }
 
@@ -1389,15 +1377,16 @@ calculate_first_last_level(struct st_texture_object *stObj)
 static void
 copy_image_data_to_texture(struct st_context *st,
                           struct st_texture_object *stObj,
+                           GLuint dstLevel,
                           struct st_texture_image *stImage)
 {
    if (stImage->pt) {
       /* Copy potentially with the blitter:
        */
       st_texture_image_copy(st->pipe,
-                            stObj->pt,  /* dest texture */
-                            stImage->face, stImage->level,
-                            stImage->pt /* src texture */
+                            stObj->pt, dstLevel,  /* dest texture, level */
+                            stImage->pt, /* src texture */
+                            stImage->face
                             );
 
       st->pipe->texture_release(st->pipe, &stImage->pt);
@@ -1438,7 +1427,7 @@ st_finalize_texture(GLcontext *ctx,
    const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
    int comp_byte = 0;
    int cpp;
-   GLuint face, i;
+   GLuint face;
    struct st_texture_image *firstImage;
 
    *needFlush = GL_FALSE;
@@ -1450,7 +1439,7 @@ st_finalize_texture(GLcontext *ctx,
    /* What levels must the texture include at a minimum?
     */
    calculate_first_last_level(stObj);
-   firstImage = st_texture_image(stObj->base.Image[0][stObj->firstLevel]);
+   firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
 
    /* Fallback case:
     */
@@ -1469,7 +1458,6 @@ st_finalize_texture(GLcontext *ctx,
     */
    if (firstImage->pt &&
        firstImage->pt != stObj->pt &&
-       firstImage->pt->first_level <= stObj->firstLevel &&
        firstImage->pt->last_level >= stObj->lastLevel) {
 
       if (stObj->pt)
@@ -1488,18 +1476,11 @@ st_finalize_texture(GLcontext *ctx,
 
    /* Check texture can hold all active levels.  Check texture matches
     * target, imageFormat, etc.
-    * 
-    * XXX: For some layouts (eg i945?), the test might have to be
-    * first_level == firstLevel, as the texture isn't valid except at the
-    * original start level.  Hope to get around this by
-    * programming minLod, maxLod, baseLevel into the hardware and
-    * leaving the texture alone.
     */
    if (stObj->pt &&
        (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
        stObj->pt->format !=
        st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat) ||
-       stObj->pt->first_level != stObj->firstLevel ||
        stObj->pt->last_level != stObj->lastLevel ||
        stObj->pt->width[0] != firstImage->base.Width ||
        stObj->pt->height[0] != firstImage->base.Height ||
@@ -1516,7 +1497,7 @@ st_finalize_texture(GLcontext *ctx,
       stObj->pt = st_texture_create(ctx->st,
                                     gl_target_to_pipe(stObj->base.Target),
                                     st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat),
-                                    stObj->firstLevel,
+                                    0, /* first level */
                                     stObj->lastLevel,
                                     firstImage->base.Width,
                                     firstImage->base.Height,
@@ -1527,14 +1508,16 @@ st_finalize_texture(GLcontext *ctx,
    /* Pull in any images not in the object's texture:
     */
    for (face = 0; face < nr_faces; face++) {
-      for (i = stObj->firstLevel; i <= stObj->lastLevel; i++) {
+      GLuint level;
+      for (level = 0; level <= stObj->lastLevel; level++) {
          struct st_texture_image *stImage =
-            st_texture_image(stObj->base.Image[face][i]);
+            //st_texture_image(stObj->base.Image[face][level]);
+            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
 
          /* Need to import images in main memory or held in other textures.
           */
          if (stObj->pt != stImage->pt) {
-            copy_image_data_to_texture(ctx->st, stObj, stImage);
+            copy_image_data_to_texture(ctx->st, stObj, level, stImage);
            *needFlush = GL_TRUE;
          }
       }
index c152c59..fd7d8ce 100644 (file)
@@ -51,7 +51,6 @@
 static void *blend_cso = NULL;
 static void *depthstencil_cso = NULL;
 static void *rasterizer_cso = NULL;
-static void *sampler_cso = NULL;
 
 static struct st_fragment_program *stfp = NULL;
 static struct st_vertex_program *stvp = NULL;
@@ -118,7 +117,6 @@ st_init_generate_mipmap(struct st_context *st)
    struct pipe_context *pipe = st->pipe;
    struct pipe_blend_state blend;
    struct pipe_rasterizer_state rasterizer;
-   struct pipe_sampler_state sampler;
    struct pipe_depth_stencil_alpha_state depthstencil;
 
    assert(!blend_cso);
@@ -133,16 +131,6 @@ st_init_generate_mipmap(struct st_context *st)
    memset(&rasterizer, 0, sizeof(rasterizer));
    rasterizer_cso = pipe->create_rasterizer_state(pipe, &rasterizer);
 
-   memset(&sampler, 0, sizeof(sampler));
-   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
-   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
-   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
-   sampler.normalized_coords = 1;
-   sampler_cso = pipe->create_sampler_state(pipe, &sampler);
-
    stfp = make_tex_fragment_program(st->ctx);
    stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
 }
@@ -156,14 +144,12 @@ st_destroy_generate_mipmpap(struct st_context *st)
    pipe->delete_blend_state(pipe, blend_cso);
    pipe->delete_depth_stencil_alpha_state(pipe, depthstencil_cso);
    pipe->delete_rasterizer_state(pipe, rasterizer_cso);
-   pipe->delete_sampler_state(pipe, sampler_cso);
 
    /* XXX free stfp, stvp */
 
    blend_cso = NULL;
    depthstencil_cso = NULL;
    rasterizer_cso = NULL;
-   sampler_cso = NULL;
 }
 
 
@@ -248,8 +234,10 @@ st_render_mipmap(struct st_context *st,
 {
    struct pipe_context *pipe = st->pipe;
    struct pipe_framebuffer_state fb;
+   struct pipe_sampler_state sampler;
+   void *sampler_cso;
    const uint face = _mesa_tex_target_to_face(target), zslice = 0;
-   const uint first_level_save = pt->first_level;
+   /*const uint first_level_save = pt->first_level;*/
    uint dstLevel;
 
    assert(target != GL_TEXTURE_3D); /* not done yet */
@@ -263,11 +251,21 @@ st_render_mipmap(struct st_context *st,
    memset(&fb, 0, sizeof(fb));
    fb.num_cbufs = 1;
 
+   /* sampler state */
+   memset(&sampler, 0, sizeof(sampler));
+   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+   sampler.normalized_coords = 1;
+
+
    /* bind CSOs */
    pipe->bind_blend_state(pipe, blend_cso);
    pipe->bind_depth_stencil_alpha_state(pipe, depthstencil_cso);
    pipe->bind_rasterizer_state(pipe, rasterizer_cso);
-   pipe->bind_sampler_state(pipe, 0, sampler_cso);
 
    /* bind shaders */
    pipe->bind_fs_state(pipe, stfp->fs->data);
@@ -286,20 +284,29 @@ st_render_mipmap(struct st_context *st,
       fb.cbufs[0] = pipe->get_tex_surface(pipe, pt, face, dstLevel, zslice);
       pipe->set_framebuffer_state(pipe, &fb);
 
+      /*
+       * Setup sampler state
+       */
+      sampler.min_lod = sampler.max_lod = srcLevel;
+      sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+      pipe->bind_sampler_state(pipe, 0, sampler_cso);
+
       simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
 
       /*
        * Setup src texture, override pt->first_level so we sample from
        * the right mipmap level.
        */
-      pt->first_level = srcLevel;
+      /*pt->first_level = srcLevel;*/
       pipe->set_sampler_texture(pipe, 0, pt);
 
       draw_quad(st->ctx);
+
+      pipe->delete_sampler_state(pipe, sampler_cso);
    }
 
    /* restore first_level */
-   pt->first_level = first_level_save;
+   /*pt->first_level = first_level_save;*/
 
    /* restore pipe state */
    if (st->state.rasterizer)
index 844a9f8..ff33da6 100644 (file)
@@ -62,6 +62,10 @@ target_to_target(GLenum target)
 
 /**
  * Allocate a new pipe_texture object
+ * width0, height0, depth0 are the dimensions of the level 0 image
+ * (the highest resolution).  last_level indicates how many mipmap levels
+ * to allocate storage for.  For non-mipmapped textures, this will be zero.
+ * XXX first_level obsolete
  */
 struct pipe_texture *
 st_texture_create(struct st_context *st,
@@ -84,9 +88,9 @@ st_texture_create(struct st_context *st,
 
    assert(format);
 
+   memset(&pt, 0, sizeof(pt));
    pt.target = target;
    pt.format = format;
-   pt.first_level = first_level;
    pt.last_level = last_level;
    pt.width[0] = width0;
    pt.height[0] = height0;
@@ -266,23 +270,36 @@ st_texture_image_data(struct pipe_context *pipe,
  */
 void
 st_texture_image_copy(struct pipe_context *pipe,
-                      struct pipe_texture *dst,
-                      GLuint face, GLuint level,
-                      struct pipe_texture *src)
+                      struct pipe_texture *dst, GLuint dstLevel,
+                      struct pipe_texture *src,
+                      GLuint face)
 {
-   GLuint width = src->width[level];
-   GLuint height = src->height[level];
-   GLuint depth = src->depth[level];
+   GLuint width = dst->width[dstLevel];
+   GLuint height = dst->height[dstLevel];
+   GLuint depth = dst->depth[dstLevel];
    struct pipe_surface *src_surface;
    struct pipe_surface *dst_surface;
    GLuint i;
 
+   /* XXX this is a hack */
    if (dst->compressed)
       height /= 4;
 
    for (i = 0; i < depth; i++) {
-      dst_surface = pipe->get_tex_surface(pipe, dst, face, level, i);
-      src_surface = pipe->get_tex_surface(pipe, src, face, level, i);
+      GLuint srcLevel;
+
+      /* find src texture level of needed size */
+      for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
+         if (src->width[srcLevel] == width &&
+             src->height[srcLevel] == height) {
+            break;
+         }
+      }
+      assert(src->width[srcLevel] == width);
+      assert(src->height[srcLevel] == height);
+
+      dst_surface = pipe->get_tex_surface(pipe, dst, face, dstLevel, i);
+      src_surface = pipe->get_tex_surface(pipe, src, face, srcLevel, i);
 
       pipe->surface_copy(pipe,
                         dst_surface,
index 0b87a49..6c5f093 100644 (file)
@@ -98,9 +98,9 @@ st_texture_image_data(struct pipe_context *pipe,
  */
 extern void
 st_texture_image_copy(struct pipe_context *pipe,
-                      struct pipe_texture *dst,
-                      GLuint face, GLuint level,
-                      struct pipe_texture *src);
+                      struct pipe_texture *dst, GLuint dstLevel,
+                      struct pipe_texture *src,
+                      GLuint face);
 
 
 #endif