st/mesa: Make st_cb_drawtex.h FEATURE_OES_draw_texture aware.
[mesa.git] / src / mesa / state_tracker / st_cb_texture.c
index a0dc016b3340f3e417f0910e599d83de0bd72628..e34fd09dcb753f468310695d74e11f2668d30e6d 100644 (file)
@@ -27,9 +27,6 @@
 
 #include "main/mfeatures.h"
 #include "main/bufferobj.h"
-#if FEATURE_convolve
-#include "main/convolve.h"
-#endif
 #include "main/enums.h"
 #include "main/fbobject.h"
 #include "main/formats.h"
 #include "state_tracker/st_debug.h"
 #include "state_tracker/st_context.h"
 #include "state_tracker/st_cb_fbo.h"
+#include "state_tracker/st_cb_flush.h"
 #include "state_tracker/st_cb_texture.h"
 #include "state_tracker/st_format.h"
-#include "state_tracker/st_public.h"
 #include "state_tracker/st_texture.h"
 #include "state_tracker/st_gen_mipmap.h"
-#include "state_tracker/st_inlines.h"
 #include "state_tracker/st_atom.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.h"
 #include "pipe/p_shader_tokens.h"
 #include "util/u_tile.h"
 #include "util/u_blit.h"
+#include "util/u_format.h"
 #include "util/u_surface.h"
+#include "util/u_sampler.h"
 #include "util/u_math.h"
 
 
@@ -119,10 +117,21 @@ static void
 st_DeleteTextureObject(GLcontext *ctx,
                        struct gl_texture_object *texObj)
 {
+   struct st_context *st = st_context(ctx);
    struct st_texture_object *stObj = st_texture_object(texObj);
    if (stObj->pt)
-      pipe_texture_reference(&stObj->pt, NULL);
-
+      pipe_resource_reference(&stObj->pt, NULL);
+   if (stObj->sampler_view) {
+      if (stObj->sampler_view->context != st->pipe) {
+         /* Take "ownership" of this texture sampler view by setting
+          * its context pointer to this context.  This avoids potential
+          * crashes when the texture object is shared among contexts
+          * and the original/owner context has already been destroyed.
+          */
+         stObj->sampler_view->context = st->pipe;
+      }
+      pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+   }
    _mesa_delete_texture_object(ctx, texObj);
 }
 
@@ -136,7 +145,7 @@ st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
    DBG("%s\n", __FUNCTION__);
 
    if (stImage->pt) {
-      pipe_texture_reference(&stImage->pt, NULL);
+      pipe_resource_reference(&stImage->pt, NULL);
    }
 
    if (texImage->Data) {
@@ -197,110 +206,142 @@ do_memcpy(void *dest, const void *src, size_t n)
 
 
 /**
- * Return default texture usage bitmask for the given texture format.
+ * Return default texture resource binding bitmask for the given format.
  */
 static GLuint
-default_usage(enum pipe_format fmt)
+default_bindings(struct st_context *st, enum pipe_format format)
 {
-   GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER;
-   if (pf_is_depth_stencil(fmt))
-      usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+   struct pipe_screen *screen = st->pipe->screen;
+   const unsigned target = PIPE_TEXTURE_2D;
+   const unsigned geom = 0x0;
+   unsigned bindings;
+
+   if (util_format_is_depth_or_stencil(format))
+      bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
+   else
+      bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+
+   if (screen->is_format_supported(screen, format, target, bindings, geom))
+      return bindings;
    else
-      usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
-   return usage;
+      return PIPE_BIND_SAMPLER_VIEW;
+}
+
+
+/** Return number of image dimensions (1, 2 or 3) for a texture target. */
+static GLuint
+get_texture_dims(GLenum target)
+{
+   switch (target) {
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_1D_ARRAY_EXT:
+      return 1;
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_CUBE_MAP_ARB:
+   case GL_TEXTURE_RECTANGLE_NV:
+   case GL_TEXTURE_2D_ARRAY_EXT:
+      return 2;
+   case GL_TEXTURE_3D:
+      return 3;
+   default:
+      assert(0 && "invalid texture target in get_texture_dims()");
+      return 1;
+   }
 }
 
 
 /**
- * Allocate a pipe_texture object for the given st_texture_object using
- * the given st_texture_image to guess the mipmap size/levels.
+ * Try to allocate a pipe_resource object for the given st_texture_object.
  *
- * [comments...]
- * Otherwise, store it in memory if (Border != 0) or (any dimension ==
- * 1).
- *    
- * Otherwise, if max_level >= level >= min_level, create texture with
- * space for images from min_level down to max_level.
+ * We use the given st_texture_image as a clue to determine the size of the
+ * mipmap image at level=0.
  *
- * Otherwise, create texture with space for images from (level 0)..(1x1).
- * Consider pruning this texture at a validation if the saving is worth it.
+ * \return GL_TRUE for success, GL_FALSE if out of memory.
  */
-static void
+static GLboolean
 guess_and_alloc_texture(struct st_context *st,
                        struct st_texture_object *stObj,
                        const struct st_texture_image *stImage)
 {
-   GLuint firstLevel;
-   GLuint lastLevel;
-   GLuint width = stImage->base.Width2;  /* size w/out border */
-   GLuint height = stImage->base.Height2;
-   GLuint depth = stImage->base.Depth2;
-   GLuint i, usage;
+   const GLuint dims = get_texture_dims(stObj->base.Target);
+   GLuint level, lastLevel, width, height, depth;
+   GLuint bindings;
    enum pipe_format fmt;
 
    DBG("%s\n", __FUNCTION__);
 
    assert(!stObj->pt);
 
-   if (stObj->pt &&
-       (GLint) stImage->level > stObj->base.BaseLevel &&
-       (stImage->base.Width == 1 ||
-        (stObj->base.Target != GL_TEXTURE_1D &&
-         stImage->base.Height == 1) ||
-        (stObj->base.Target == GL_TEXTURE_3D &&
-         stImage->base.Depth == 1)))
-      return;
+   level = stImage->level;
+   width = stImage->base.Width2;  /* size w/out border */
+   height = stImage->base.Height2;
+   depth = stImage->base.Depth2;
 
-   /* If this image disrespects BaseLevel, allocate from level zero.
-    * Usually BaseLevel == 0, so it's unlikely to happen.
-    */
-   if ((GLint) stImage->level < stObj->base.BaseLevel)
-      firstLevel = 0;
-   else
-      firstLevel = stObj->base.BaseLevel;
+   assert(width > 0);
+   assert(height > 0);
+   assert(depth > 0);
 
-
-   /* Figure out image dimensions at start level. 
+   /* Depending on the image's size, we can't always make a guess here.
     */
-   for (i = stImage->level; i > firstLevel; i--) {
+   if (level > 0) {
+      if ( (dims >= 1 && width == 1) ||
+           (dims >= 2 && height == 1) ||
+           (dims >= 3 && depth == 1) ) {
+         /* we can't determine the image size at level=0 */
+         stObj->width0 = stObj->height0 = stObj->depth0 = 0;
+         /* this is not an out of memory error */
+         return GL_TRUE;
+      }
+   }
+
+   /* grow the image size until we hit level = 0 */
+   while (level > 0) {
       if (width != 1)
          width <<= 1;
       if (height != 1)
          height <<= 1;
       if (depth != 1)
          depth <<= 1;
-   }
+      level--;
+   }      
 
-   if (width == 0 || height == 0 || depth == 0) {
-      /* no texture needed */
-      return;
-   }
+   assert(level == 0);
+
+   /* At this point, (width x height x depth) is the expected size of
+    * the level=0 mipmap image.
+    */
 
-   /* Guess a reasonable value for lastLevel.  This is probably going
-    * to be wrong fairly often and might mean that we have to look at
-    * resizable buffers, or require that buffers implement lazy
-    * pagetable arrangements.
+   /* Guess a reasonable value for lastLevel.  With OpenGL we have no
+    * idea how many mipmap levels will be in a texture until we start
+    * to render with it.  Make an educated guess here but be prepared
+    * to re-allocating a texture buffer with space for more (or fewer)
+    * mipmap levels later.
     */
    if ((stObj->base.MinFilter == GL_NEAREST ||
         stObj->base.MinFilter == GL_LINEAR ||
         stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||
         stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&
        !stObj->base.GenerateMipmap &&
-       stImage->level == firstLevel) {
+       stImage->level == 0) {
       /* only alloc space for a single mipmap level */
-      lastLevel = firstLevel;
+      lastLevel = 0;
    }
    else {
       /* alloc space for a full mipmap */
       GLuint l2width = util_logbase2(width);
       GLuint l2height = util_logbase2(height);
       GLuint l2depth = util_logbase2(depth);
-      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
+      lastLevel = MAX2(MAX2(l2width, l2height), l2depth);
    }
 
+   /* Save the level=0 dimensions */
+   stObj->width0 = width;
+   stObj->height0 = height;
+   stObj->depth0 = depth;
+
    fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);
 
-   usage = default_usage(fmt);
+   bindings = default_bindings(st, fmt);
 
    stObj->pt = st_texture_create(st,
                                  gl_target_to_pipe(stObj->base.Target),
@@ -309,9 +350,11 @@ guess_and_alloc_texture(struct st_context *st,
                                  width,
                                  height,
                                  depth,
-                                 usage);
+                                 bindings);
+
+   DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
 
-   DBG("%s - success\n", __FUNCTION__);
+   return stObj->pt != NULL;
 }
 
 
@@ -370,10 +413,14 @@ compress_with_blit(GLcontext * ctx,
 {
    const GLuint dstImageOffsets[1] = {0};
    struct st_texture_image *stImage = st_texture_image(texImage);
-   struct pipe_screen *screen = ctx->st->pipe->screen;
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_screen *screen = pipe->screen;
    gl_format mesa_format;
-   struct pipe_texture templ;
-   struct pipe_texture *src_tex;
+   struct pipe_resource templ;
+   struct pipe_resource *src_tex;
+   struct pipe_sampler_view view_templ;
+   struct pipe_sampler_view *src_view;
    struct pipe_surface *dst_surface;
    struct pipe_transfer *tex_xfer;
    void *map;
@@ -386,7 +433,7 @@ compress_with_blit(GLcontext * ctx,
    /* get destination surface (in the compressed texture) */
    dst_surface = screen->get_tex_surface(screen, stImage->pt,
                                          stImage->face, stImage->level, 0,
-                                         PIPE_BUFFER_USAGE_GPU_WRITE);
+                                         PIPE_BIND_BLIT_DESTINATION);
    if (!dst_surface) {
       /* can't render into this format (or other problem) */
       return GL_FALSE;
@@ -404,24 +451,24 @@ compress_with_blit(GLcontext * ctx,
    memset(&templ, 0, sizeof(templ));
    templ.target = PIPE_TEXTURE_2D;
    templ.format = st_mesa_format_to_pipe_format(mesa_format);
-   pf_get_block(templ.format, &templ.block);
-   templ.width[0] = width;
-   templ.height[0] = height;
-   templ.depth[0] = 1;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
    templ.last_level = 0;
-   templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
-   src_tex = screen->texture_create(screen, &templ);
+   templ.usage = PIPE_USAGE_DEFAULT;
+   templ.bind = PIPE_BIND_SAMPLER_VIEW;
+   src_tex = screen->resource_create(screen, &templ);
 
    if (!src_tex)
       return GL_FALSE;
 
    /* Put user's tex data into the temporary texture
     */
-   tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex,
+   tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex,
                                             0, 0, 0, /* face, level are zero */
                                             PIPE_TRANSFER_WRITE,
                                             0, 0, width, height); /* x, y, w, h */
-   map = screen->transfer_map(screen, tex_xfer);
+   map = pipe_transfer_map(pipe, tex_xfer);
 
    _mesa_texstore(ctx, 2, GL_RGBA, mesa_format,
                   map,              /* dest ptr */
@@ -433,12 +480,19 @@ compress_with_blit(GLcontext * ctx,
                   pixels,           /* source data */
                   unpack);          /* source data packing */
 
-   screen->transfer_unmap(screen, tex_xfer);
-   screen->tex_transfer_destroy(tex_xfer);
+   pipe_transfer_unmap(pipe, tex_xfer);
+   pipe->transfer_destroy(pipe, tex_xfer);
+
+   /* Create temporary sampler view */
+   u_sampler_view_default_template(&view_templ,
+                                   src_tex,
+                                   src_tex->format);
+   src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ);
+
 
    /* copy / compress image */
-   util_blit_pixels_tex(ctx->st->blit,
-                        src_tex,          /* pipe_texture (src) */
+   util_blit_pixels_tex(st->blit,
+                        src_view,         /* sampler view (src) */
                         0, 0,             /* src x0, y0 */
                         width, height,    /* src x1, y1 */
                         dst_surface,      /* pipe_surface (dst) */
@@ -449,7 +503,8 @@ compress_with_blit(GLcontext * ctx,
                         PIPE_TEX_MIPFILTER_NEAREST);
 
    pipe_surface_reference(&dst_surface, NULL);
-   pipe_texture_reference(&src_tex, NULL);
+   pipe_resource_reference(&src_tex, NULL);
+   pipe_sampler_view_reference(&src_view, NULL);
 
    return GL_TRUE;
 }
@@ -471,11 +526,10 @@ st_TexImage(GLcontext * ctx,
             struct gl_texture_image *texImage,
             GLsizei imageSize, GLboolean compressed_src)
 {
-   struct pipe_screen *screen = ctx->st->pipe->screen;
+   struct st_context *st = st_context(ctx);
+   struct pipe_screen *screen = st->pipe->screen;
    struct st_texture_object *stObj = st_texture_object(texObj);
    struct st_texture_image *stImage = st_texture_image(texImage);
-   GLint postConvWidth, postConvHeight;
-   GLint texelBytes, sizeInBytes;
    GLuint dstRowStride = 0;
    struct gl_pixelstore_attrib unpackNB;
    enum pipe_transfer_usage transfer_usage = 0;
@@ -483,6 +537,12 @@ st_TexImage(GLcontext * ctx,
    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
        _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
 
+   /* The Mesa/Gallium state tracker does not implement the imaging extensions
+    * such as convolution.
+    */
+   assert(!ctx->Extensions.ARB_imaging);
+   assert(!ctx->Extensions.EXT_convolution);
+
    /* switch to "normal" */
    if (stObj->surface_based) {
       _mesa_clear_texture_object(ctx, texObj);
@@ -499,82 +559,55 @@ st_TexImage(GLcontext * ctx,
       texImage->Border = 0;
       border = 0;
    }
-
-   postConvWidth = width;
-   postConvHeight = height;
+   else {
+      assert(texImage->Width == width);
+      assert(texImage->Height == height);
+      assert(texImage->Depth == depth);
+   }
 
    stImage->face = _mesa_tex_target_to_face(target);
    stImage->level = level;
 
-#if FEATURE_convolve
-   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
-      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
-                                         &postConvHeight);
-   }
-#endif
-
    _mesa_set_fetch_functions(texImage, dims);
 
-   if (_mesa_is_format_compressed(texImage->TexFormat)) {
-      /* must be a compressed format */
-      texelBytes = 0;
-   }
-   else {
-      texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
-      
-      /* Minimum pitch of 32 bytes */
-      if (postConvWidth * texelBytes < 32) {
-        postConvWidth = 32 / texelBytes;
-        texImage->RowStride = postConvWidth;
-      }
-      
-      /* we'll set RowStride elsewhere when the texture is a "mapped" state */
-      /*assert(texImage->RowStride == postConvWidth);*/
-   }
-
    /* Release the reference to a potentially orphaned buffer.   
     * Release any old malloced memory.
     */
    if (stImage->pt) {
-      pipe_texture_reference(&stImage->pt, NULL);
+      pipe_resource_reference(&stImage->pt, NULL);
       assert(!texImage->Data);
    }
    else if (texImage->Data) {
       _mesa_align_free(texImage->Data);
    }
 
-   if (width == 0 || height == 0 || depth == 0) {
-      /* stop after freeing old image */
-      return;
-   }
-
-   /* 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.
+   /*
+    * See if the new image is somehow incompatible with the existing
+    * mipmap.  If so, free the old mipmap.
     */
    if (stObj->pt) {
-      if (stObj->teximage_realloc ||
-          level > (GLint) stObj->pt->last_level ||
-          (stObj->pt->last_level == level &&
-           stObj->pt->target != PIPE_TEXTURE_CUBE &&
-           !st_texture_match_image(stObj->pt, &stImage->base,
-                                   stImage->face, stImage->level))) {
+      if (level > (GLint) stObj->pt->last_level ||
+          !st_texture_match_image(stObj->pt, &stImage->base,
+                                  stImage->face, stImage->level)) {
          DBG("release it\n");
-         pipe_texture_reference(&stObj->pt, NULL);
+         pipe_resource_reference(&stObj->pt, NULL);
          assert(!stObj->pt);
-         stObj->teximage_realloc = FALSE;
+         pipe_sampler_view_reference(&stObj->sampler_view, NULL);
       }
    }
 
+   if (width == 0 || height == 0 || depth == 0) {
+      /* stop after freeing old image */
+      return;
+   }
+
    if (!stObj->pt) {
-      guess_and_alloc_texture(ctx->st, stObj, stImage);
-      if (!stObj->pt) {
+      if (!guess_and_alloc_texture(st, stObj, stImage)) {
          /* Probably out of memory.
           * Try flushing any pending rendering, then retry.
           */
-         st_finish(ctx->st);
-         guess_and_alloc_texture(ctx->st, stObj, stImage);
-         if (!stObj->pt) {
+         st_finish(st);
+         if (!guess_and_alloc_texture(st, stObj, stImage)) {
             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
             return;
          }
@@ -583,20 +616,26 @@ st_TexImage(GLcontext * ctx,
 
    assert(!stImage->pt);
 
+   /* Check if this texture image can live inside the texture object's buffer.
+    * If so, store the image there.  Otherwise the image will temporarily live
+    * in its own buffer.
+    */
    if (stObj->pt &&
        st_texture_match_image(stObj->pt, &stImage->base,
-                                 stImage->face, stImage->level)) {
+                              stImage->face, stImage->level)) {
 
-      pipe_texture_reference(&stImage->pt, stObj->pt);
+      pipe_resource_reference(&stImage->pt, stObj->pt);
       assert(stImage->pt);
    }
 
    if (!stImage->pt)
       DBG("XXX: Image did not fit into texture - storing in local memory!\n");
 
-   /* st_CopyTexImage calls this function with pixels == NULL, with
-    * the expectation that the texture will be set up but nothing
-    * more will be done.  This is where those calls return:
+   /* Pixel data may come from regular user memory or a PBO.  For the later,
+    * do bounds checking and map the PBO to read pixels data from it.
+    *
+    * XXX we should try to use a GPU-accelerated path to copy the image data
+    * from the PBO to the texture.
     */
    if (compressed_src) {
       pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
@@ -609,10 +648,6 @@ st_TexImage(GLcontext * ctx,
                                           pixels, unpack, "glTexImage");
    }
 
-   /* Note: we can't check for pixels==NULL until after we've allocated
-    * memory for the texture.
-    */
-
    /* See if we can do texture compression with a blit/render.
     */
    if (!compressed_src &&
@@ -621,7 +656,7 @@ st_TexImage(GLcontext * ctx,
        screen->is_format_supported(screen,
                                    stImage->pt->format,
                                    stImage->pt->target,
-                                   PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+                                   PIPE_BIND_RENDER_TARGET, 0)) {
       if (!pixels)
          goto done;
 
@@ -631,36 +666,30 @@ st_TexImage(GLcontext * ctx,
       }
    }
 
+   /*
+    * Prepare to store the texture data.  Either map the gallium texture buffer
+    * memory or malloc space for it.
+    */
    if (stImage->pt) {
+      /* Store the image in the gallium texture memory buffer */
       if (format == GL_DEPTH_COMPONENT &&
-          pf_is_depth_and_stencil(stImage->pt->format))
+          util_format_is_depth_and_stencil(stImage->pt->format))
          transfer_usage = PIPE_TRANSFER_READ_WRITE;
       else
          transfer_usage = PIPE_TRANSFER_WRITE;
 
-      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
-                                            transfer_usage, 0, 0,
-                                            stImage->base.Width,
-                                            stImage->base.Height);
+      texImage->Data = st_texture_image_map(st, stImage, 0,
+                                            transfer_usage, 0, 0, width, height);
       if(stImage->transfer)
          dstRowStride = stImage->transfer->stride;
    }
    else {
       /* Allocate regular memory and store the image there temporarily.   */
-      if (_mesa_is_format_compressed(texImage->TexFormat)) {
-         sizeInBytes = _mesa_format_image_size(texImage->TexFormat,
-                                               texImage->Width,
-                                               texImage->Height,
-                                               texImage->Depth);
-         dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
-         assert(dims != 3);
-      }
-      else {
-         dstRowStride = postConvWidth * texelBytes;
-         sizeInBytes = depth * dstRowStride * postConvHeight;
-      }
+      GLuint imageSize = _mesa_format_image_size(texImage->TexFormat,
+                                                 width, height, depth);
+      dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
 
-      texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
+      texImage->Data = _mesa_align_malloc(imageSize, 16);
    }
 
    if (!texImage->Data) {
@@ -668,18 +697,35 @@ st_TexImage(GLcontext * ctx,
       return;
    }
 
-   if (!pixels)
+   if (!pixels) {
+      /* We've allocated texture memory, but have no pixel data - all done. */
       goto done;
+   }
 
    DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
-       width, height, depth, width * texelBytes, dstRowStride);
+       width, height, depth, width, dstRowStride);
 
-   /* Copy data.  Would like to know when it's ok for us to eg. use
-    * the blitter to copy.  Or, use the hardware to do the format
-    * conversion and copy:
+   /* Copy user texture image into the texture buffer.
     */
    if (compressed_src) {
-      memcpy(texImage->Data, pixels, imageSize);
+      const GLuint srcRowStride =
+         _mesa_format_row_stride(texImage->TexFormat, width);
+      if (dstRowStride == srcRowStride) {
+         memcpy(texImage->Data, pixels, imageSize);
+      }
+      else {
+         char *dst = texImage->Data;
+         const char *src = pixels;
+         GLuint i, bw, bh, lines;
+         _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
+         lines = (height + bh - 1) / bh;
+
+         for (i = 0; i < lines; ++i) {
+            memcpy(dst, src, srcRowStride);
+            dst += dstRowStride;
+            src += srcRowStride;
+         }
+      }
    }
    else {
       const GLuint srcImageStride =
@@ -702,12 +748,11 @@ st_TexImage(GLcontext * ctx,
 
         if (stImage->pt && i + 1 < depth) {
             /* unmap this slice */
-           st_texture_image_unmap(ctx->st, stImage);
+           st_texture_image_unmap(st, stImage);
             /* map next slice of 3D texture */
-           texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
+           texImage->Data = st_texture_image_map(st, stImage, i + 1,
                                                   transfer_usage, 0, 0,
-                                                  stImage->base.Width,
-                                                  stImage->base.Height);
+                                                  width, height);
            src += srcImageStride;
         }
       }
@@ -717,7 +762,7 @@ done:
    _mesa_unmap_teximage_pbo(ctx, unpack);
 
    if (stImage->pt && texImage->Data) {
-      st_texture_image_unmap(ctx->st, stImage);
+      st_texture_image_unmap(st, stImage);
       texImage->Data = NULL;
    }
 }
@@ -794,16 +839,24 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
                      struct gl_texture_object *texObj,
                      struct gl_texture_image *texImage)
 {
-   struct pipe_screen *screen = ctx->st->pipe->screen;
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_screen *screen = pipe->screen;
    struct st_texture_image *stImage = st_texture_image(texImage);
+   struct st_texture_object *stObj = st_texture_object(texObj);
+   struct pipe_sampler_view *src_view =
+      st_get_texture_sampler_view(stObj, pipe);
    const GLuint width = texImage->Width;
    const GLuint height = texImage->Height;
    struct pipe_surface *dst_surface;
-   struct pipe_texture *dst_texture;
+   struct pipe_resource *dst_texture;
    struct pipe_transfer *tex_xfer;
+   unsigned bind = (PIPE_BIND_BLIT_DESTINATION |
+                   PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */
+                   PIPE_BIND_TRANSFER_READ);
 
    /* create temp / dest surface */
-   if (!util_create_rgba_surface(screen, width, height,
+   if (!util_create_rgba_surface(screen, width, height, bind,
                                  &dst_texture, &dst_surface)) {
       _mesa_problem(ctx, "util_create_rgba_surface() failed "
                     "in decompress_with_blit()");
@@ -811,8 +864,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
    }
 
    /* blit/render/decompress */
-   util_blit_pixels_tex(ctx->st->blit,
-                        stImage->pt,      /* pipe_texture (src) */
+   util_blit_pixels_tex(st->blit,
+                        src_view,      /* pipe_resource (src) */
                         0, 0,             /* src x0, y0 */
                         width, height,    /* src x1, y1 */
                         dst_surface,      /* pipe_surface (dst) */
@@ -822,7 +875,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
                         PIPE_TEX_MIPFILTER_NEAREST);
 
    /* map the dst_surface so we can read from it */
-   tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+   tex_xfer = pipe_get_transfer(st_context(ctx)->pipe,
                                             dst_texture, 0, 0, 0,
                                             PIPE_TRANSFER_READ,
                                             0, 0, width, height);
@@ -832,8 +885,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
    /* copy/pack data into user buffer */
    if (st_equal_formats(stImage->pt->format, format, type)) {
       /* memcpy */
-      const uint bytesPerRow = width * pf_get_size(stImage->pt->format);
-      ubyte *map = screen->transfer_map(screen, tex_xfer);
+      const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
+      ubyte *map = pipe_transfer_map(pipe, tex_xfer);
       GLuint row;
       for (row = 0; row < height; row++) {
          GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
@@ -841,7 +894,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
          memcpy(dest, map, bytesPerRow);
          map += tex_xfer->stride;
       }
-      screen->transfer_unmap(screen, tex_xfer);
+      pipe_transfer_unmap(pipe, tex_xfer);
    }
    else {
       /* format translation via floats */
@@ -856,7 +909,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
             debug_printf("%s: fallback format translation\n", __FUNCTION__);
 
          /* get float[4] rgba row from surface */
-         pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba);
+         pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba);
 
          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                     type, dest, &ctx->Pack, transferOps);
@@ -865,6 +918,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
 
    _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
 
+   pipe->transfer_destroy(pipe, tex_xfer);
+
    /* destroy the temp / dest surface */
    util_destroy_rgba_surface(dst_texture, dst_surface);
 }
@@ -881,6 +936,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
                  struct gl_texture_object *texObj,
                  struct gl_texture_image *texImage, GLboolean compressed_dst)
 {
+   struct st_context *st = st_context(ctx);
    struct st_texture_image *stImage = st_texture_image(texImage);
    const GLuint dstImageStride =
       _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height,
@@ -889,7 +945,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
    GLubyte *dest;
 
    if (stImage->pt &&
-       pf_is_compressed(stImage->pt->format) &&
+       util_format_is_s3tc(stImage->pt->format) &&
        !compressed_dst) {
       /* Need to decompress the texture.
        * We'll do this by rendering a textured quad.
@@ -905,16 +961,14 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
       /* Image is stored in hardware format in a buffer managed by the
        * kernel.  Need to explicitly map and unmap it.
        */
-      unsigned face = _mesa_tex_target_to_face(target);
-
-      st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
-                                  PIPE_TRANSFER_READ);
-
-      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+      texImage->Data = st_texture_image_map(st, stImage, 0,
                                             PIPE_TRANSFER_READ, 0, 0,
                                             stImage->base.Width,
                                             stImage->base.Height);
-      texImage->RowStride = stImage->transfer->stride / stImage->pt->block.size;
+      /* compute stride in texels from stride in bytes */
+      texImage->RowStride = stImage->transfer->stride
+         * util_format_get_blockwidth(stImage->pt->format)
+         / util_format_get_blocksize(stImage->pt->format);
    }
    else {
       /* Otherwise, the image should actually be stored in
@@ -945,9 +999,9 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
 
       if (stImage->pt && i + 1 < depth) {
          /* unmap this slice */
-        st_texture_image_unmap(ctx->st, stImage);
+        st_texture_image_unmap(st, stImage);
          /* map next slice of 3D texture */
-        texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
+        texImage->Data = st_texture_image_map(st, stImage, i + 1,
                                                PIPE_TRANSFER_READ, 0, 0,
                                                stImage->base.Width,
                                                stImage->base.Height);
@@ -959,7 +1013,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
 
    /* Unmap */
    if (stImage->pt) {
-      st_texture_image_unmap(ctx->st, stImage);
+      st_texture_image_unmap(st, stImage);
       texImage->Data = NULL;
    }
 }
@@ -997,7 +1051,8 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
                struct gl_texture_object *texObj,
                struct gl_texture_image *texImage)
 {
-   struct pipe_screen *screen = ctx->st->pipe->screen;
+   struct st_context *st = st_context(ctx);
+   struct pipe_screen *screen = st->pipe->screen;
    struct st_texture_image *stImage = st_texture_image(texImage);
    GLuint dstRowStride;
    const GLuint srcImageStride =
@@ -1024,7 +1079,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
        screen->is_format_supported(screen,
                                    stImage->pt->format,
                                    stImage->pt->target,
-                                   PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+                                   PIPE_BIND_RENDER_TARGET, 0)) {
       if (compress_with_blit(ctx, target, level,
                              xoffset, yoffset, zoffset,
                              width, height, depth,
@@ -1037,17 +1092,13 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
     * from uploading the buffer under us.
     */
    if (stImage->pt) {
-      unsigned face = _mesa_tex_target_to_face(target);
-
       if (format == GL_DEPTH_COMPONENT &&
-          pf_is_depth_and_stencil(stImage->pt->format))
+          util_format_is_depth_and_stencil(stImage->pt->format))
          transfer_usage = PIPE_TRANSFER_READ_WRITE;
       else
          transfer_usage = PIPE_TRANSFER_WRITE;
 
-      st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
-                                  transfer_usage);
-      texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, 
+      texImage->Data = st_texture_image_map(st, stImage, zoffset, 
                                             transfer_usage,
                                             xoffset, yoffset,
                                             width, height);
@@ -1075,9 +1126,9 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
 
       if (stImage->pt && i + 1 < depth) {
          /* unmap this slice */
-        st_texture_image_unmap(ctx->st, stImage);
+        st_texture_image_unmap(st, stImage);
          /* map next slice of 3D texture */
-        texImage->Data = st_texture_image_map(ctx->st, stImage,
+        texImage->Data = st_texture_image_map(st, stImage,
                                                zoffset + i + 1,
                                                transfer_usage,
                                                xoffset, yoffset,
@@ -1090,7 +1141,7 @@ done:
    _mesa_unmap_teximage_pbo(ctx, packing);
 
    if (stImage->pt && texImage->Data) {
-      st_texture_image_unmap(ctx->st, stImage);
+      st_texture_image_unmap(st, stImage);
       texImage->Data = NULL;
    }
 }
@@ -1161,24 +1212,22 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
                            struct gl_texture_object *texObj,
                            struct gl_texture_image *texImage)
 {
+   struct st_context *st = st_context(ctx);
    struct st_texture_image *stImage = st_texture_image(texImage);
-   struct pipe_format_block block;
    int srcBlockStride;
    int dstBlockStride;
    int y;
+   enum pipe_format pformat;
 
    if (stImage->pt) {
-      unsigned face = _mesa_tex_target_to_face(target);
+      pformat = stImage->pt->format;
 
-      st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
-                                  PIPE_TRANSFER_WRITE);
-      texImage->Data = st_texture_image_map(ctx->st, stImage, 0, 
+      texImage->Data = st_texture_image_map(st, stImage, 0, 
                                             PIPE_TRANSFER_WRITE,
                                             xoffset, yoffset,
                                             width, height);
       
-      block = stImage->pt->block;
-      srcBlockStride = pf_get_stride(&block, width);
+      srcBlockStride = util_format_get_stride(pformat, width);
       dstBlockStride = stImage->transfer->stride;
    } else {
       assert(stImage->pt);
@@ -1192,20 +1241,20 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   assert(xoffset % block.width == 0);
-   assert(yoffset % block.height == 0);
-   assert(width % block.width == 0);
-   assert(height % block.height == 0);
+   assert(xoffset % util_format_get_blockwidth(pformat) == 0);
+   assert(yoffset % util_format_get_blockheight(pformat) == 0);
+   assert(width % util_format_get_blockwidth(pformat) == 0);
+   assert(height % util_format_get_blockheight(pformat) == 0);
 
-   for (y = 0; y < height; y += block.height) {
+   for (y = 0; y < height; y += util_format_get_blockheight(pformat)) {
       /* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */
-      const char *src = (const char*)data + srcBlockStride * pf_get_nblocksy(&block, y);
-      char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(&block, y);
-      memcpy(dst, src, pf_get_stride(&block, width));
+      const char *src = (const char*)data + srcBlockStride * util_format_get_nblocksy(pformat, y);
+      char *dst = (char*)texImage->Data + dstBlockStride * util_format_get_nblocksy(pformat, y);
+      memcpy(dst, src, util_format_get_stride(pformat, width));
    }
 
    if (stImage->pt) {
-      st_texture_image_unmap(ctx->st, stImage);
+      st_texture_image_unmap(st, stImage);
       texImage->Data = NULL;
    }
 }
@@ -1241,8 +1290,8 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
                           GLint srcX, GLint srcY,
                           GLsizei width, GLsizei height)
 {
-   struct pipe_context *pipe = ctx->st->pipe;
-   struct pipe_screen *screen = pipe->screen;
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
    struct pipe_transfer *src_trans;
    GLvoid *texDest;
    enum pipe_transfer_usage transfer_usage;
@@ -1256,7 +1305,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
       srcY = strb->Base.Height - srcY - height;
    }
 
-   src_trans = st_cond_flush_get_tex_transfer( st_context(ctx),
+   src_trans = pipe_get_transfer(st_context(ctx)->pipe,
                                               strb->texture,
                                               0, 0, 0,
                                               PIPE_TRANSFER_READ,
@@ -1265,15 +1314,12 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
 
    if ((baseFormat == GL_DEPTH_COMPONENT ||
         baseFormat == GL_DEPTH_STENCIL) &&
-       pf_is_depth_and_stencil(stImage->pt->format))
+       util_format_is_depth_and_stencil(stImage->pt->format))
       transfer_usage = PIPE_TRANSFER_READ_WRITE;
    else
       transfer_usage = PIPE_TRANSFER_WRITE;
 
-   st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0,
-                               transfer_usage);
-
-   texDest = st_texture_image_map(ctx->st, stImage, 0, transfer_usage,
+   texDest = st_texture_image_map(st, stImage, 0, transfer_usage,
                                   destX, destY, width, height);
 
    if (baseFormat == GL_DEPTH_COMPONENT ||
@@ -1295,17 +1341,17 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
       /* To avoid a large temp memory allocation, do copy row by row */
       for (row = 0; row < height; row++, srcY += yStep) {
          uint data[MAX_WIDTH];
-         pipe_get_tile_z(src_trans, 0, srcY, width, 1, data);
+         pipe_get_tile_z(pipe, src_trans, 0, srcY, width, 1, data);
          if (scaleOrBias) {
             _mesa_scale_and_bias_depth_uint(ctx, width, data);
          }
-         pipe_put_tile_z(stImage->transfer, 0, row, width, 1, data);
+         pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data);
       }
    }
    else {
       /* RGBA format */
       GLfloat *tempSrc =
-         (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+         (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
       if (tempSrc && texDest) {
          const GLint dims = 2;
@@ -1321,7 +1367,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
          /* XXX this usually involves a lot of int/float conversion.
           * try to avoid that someday.
           */
-         pipe_get_tile_rgba(src_trans, 0, 0, width, height, tempSrc);
+         pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc);
 
          /* Store into texture memory.
           * Note that this does some special things such as pixel transfer
@@ -1345,11 +1391,11 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
       }
 
       if (tempSrc)
-         _mesa_free(tempSrc);
+         free(tempSrc);
    }
 
-   st_texture_image_unmap(ctx->st, stImage);
-   screen->tex_transfer_destroy(src_trans);
+   st_texture_image_unmap(st, stImage);
+   pipe->transfer_destroy(pipe, src_trans);
 }
 
 
@@ -1444,7 +1490,8 @@ st_copy_texsubimage(GLcontext *ctx,
    const GLenum texBaseFormat = texImage->_BaseFormat;
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct st_renderbuffer *strb;
-   struct pipe_context *pipe = ctx->st->pipe;
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = pipe->screen;
    enum pipe_format dest_format, src_format;
    GLboolean use_fallback = GL_TRUE;
@@ -1453,12 +1500,9 @@ st_copy_texsubimage(GLcontext *ctx,
    struct pipe_surface *dest_surface = NULL;
    GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
 
-   /* any rendering in progress must flushed before we grab the fb image */
-   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
    /* make sure finalize_textures has been called? 
     */
-   if (0) st_validate_state(ctx->st);
+   if (0) st_validate_state(st);
 
    /* determine if copying depth or color data */
    if (texBaseFormat == GL_DEPTH_COMPONENT ||
@@ -1525,8 +1569,7 @@ st_copy_texsubimage(GLcontext *ctx,
 
    if (ctx->_ImageTransferState == 0x0) {
 
-      if (pipe->surface_copy &&
-          matching_base_formats &&
+      if (matching_base_formats &&
           src_format == dest_format &&
           !do_flip) 
       {
@@ -1535,7 +1578,7 @@ st_copy_texsubimage(GLcontext *ctx,
          dest_surface = screen->get_tex_surface(screen, stImage->pt,
                                                 stImage->face, stImage->level,
                                                 destZ,
-                                                PIPE_BUFFER_USAGE_GPU_WRITE);
+                                                PIPE_BIND_BLIT_DESTINATION);
 
          /* for surface_copy(), y=0=top, always */
          pipe->surface_copy(pipe,
@@ -1554,11 +1597,11 @@ st_copy_texsubimage(GLcontext *ctx,
                texBaseFormat != GL_DEPTH_STENCIL &&
                screen->is_format_supported(screen, src_format,
                                            PIPE_TEXTURE_2D, 
-                                           PIPE_TEXTURE_USAGE_SAMPLER,
+                                           PIPE_BIND_SAMPLER_VIEW,
                                            0) &&
                screen->is_format_supported(screen, dest_format,
                                            PIPE_TEXTURE_2D, 
-                                           PIPE_TEXTURE_USAGE_RENDER_TARGET,
+                                           PIPE_BIND_RENDER_TARGET,
                                            0)) {
          /* draw textured quad to do the copy */
          GLint srcY0, srcY1;
@@ -1566,7 +1609,7 @@ st_copy_texsubimage(GLcontext *ctx,
          dest_surface = screen->get_tex_surface(screen, stImage->pt,
                                                 stImage->face, stImage->level,
                                                 destZ,
-                                                PIPE_BUFFER_USAGE_GPU_WRITE);
+                                                PIPE_BIND_BLIT_DESTINATION);
 
          if (do_flip) {
             srcY1 = strb->Base.Height - srcY - height;
@@ -1576,8 +1619,9 @@ st_copy_texsubimage(GLcontext *ctx,
             srcY0 = srcY;
             srcY1 = srcY0 + height;
          }
-         util_blit_pixels_writemask(ctx->st->blit,
+         util_blit_pixels_writemask(st->blit,
                                     strb->surface,
+                                    st_get_renderbuffer_sampler_view(strb, pipe),
                                     srcX, srcY0,
                                     srcX + width, srcY1,
                                     dest_surface,
@@ -1691,46 +1735,52 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
 }
 
 
+/**
+ * Copy image data from stImage into the texture object 'stObj' at level
+ * 'dstLevel'.
+ */
 static void
 copy_image_data_to_texture(struct st_context *st,
                           struct st_texture_object *stObj,
                            GLuint dstLevel,
                           struct st_texture_image *stImage)
 {
+   /* debug checks */
+   {
+      const struct gl_texture_image *dstImage =
+         stObj->base.Image[stImage->face][stImage->level];
+      assert(dstImage);
+      assert(dstImage->Width == stImage->base.Width);
+      assert(dstImage->Height == stImage->base.Height);
+      assert(dstImage->Depth == stImage->base.Depth);
+   }
+
    if (stImage->pt) {
       /* Copy potentially with the blitter:
        */
       st_texture_image_copy(st->pipe,
                             stObj->pt, dstLevel,  /* dest texture, level */
-                            stImage->pt, /* src texture */
-                            stImage->face
-                            );
+                            stImage->pt, stImage->level, /* src texture, level */
+                            stImage->face);
 
-      pipe_texture_reference(&stImage->pt, NULL);
+      pipe_resource_reference(&stImage->pt, NULL);
    }
    else if (stImage->base.Data) {
-      /* More straightforward upload.  
-       */
-
-      st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel,
-                                  PIPE_TRANSFER_WRITE);
-
-
       st_texture_image_data(st,
                             stObj->pt,
                             stImage->face,
                             dstLevel,
                             stImage->base.Data,
                             stImage->base.RowStride * 
-                            stObj->pt->block.size,
+                            util_format_get_blocksize(stObj->pt->format),
                             stImage->base.RowStride *
                             stImage->base.Height *
-                            stObj->pt->block.size);
+                            util_format_get_blocksize(stObj->pt->format));
       _mesa_align_free(stImage->base.Data);
       stImage->base.Data = NULL;
    }
 
-   pipe_texture_reference(&stImage->pt, stObj->pt);
+   pipe_resource_reference(&stImage->pt, stObj->pt);
 }
 
 
@@ -1742,15 +1792,14 @@ copy_image_data_to_texture(struct st_context *st,
 GLboolean
 st_finalize_texture(GLcontext *ctx,
                    struct pipe_context *pipe,
-                   struct gl_texture_object *tObj,
-                   GLboolean *needFlush)
+                   struct gl_texture_object *tObj)
 {
+   struct st_context *st = st_context(ctx);
    struct st_texture_object *stObj = st_texture_object(tObj);
    const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
-   GLuint blockSize, face;
+   GLuint face;
    struct st_texture_image *firstImage;
-
-   *needFlush = GL_FALSE;
+   enum pipe_format firstImageFormat;
 
    if (stObj->base._Complete) {
       /* The texture is complete and we know exactly how many mipmap levels
@@ -1763,10 +1812,11 @@ st_finalize_texture(GLcontext *ctx,
           stObj->base.MinFilter == GL_NEAREST)
          stObj->lastLevel = stObj->base.BaseLevel;
       else
-         stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel;
+         stObj->lastLevel = stObj->base._MaxLevel;
    }
 
    firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+   assert(firstImage);
 
    /* If both firstImage and stObj point to a texture which can contain
     * all active images, favour firstImage.  Note that because of the
@@ -1776,46 +1826,46 @@ st_finalize_texture(GLcontext *ctx,
    if (firstImage->pt &&
        firstImage->pt != stObj->pt &&
        firstImage->pt->last_level >= stObj->lastLevel) {
-      pipe_texture_reference(&stObj->pt, firstImage->pt);
+      pipe_resource_reference(&stObj->pt, firstImage->pt);
+      pipe_sampler_view_reference(&stObj->sampler_view, NULL);
    }
 
-   /* bytes per pixel block (blocks are usually 1x1) */
-   blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat);
+   /* Find gallium format for the Mesa texture */
+   firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
 
    /* If we already have a gallium texture, check that it matches the texture
     * object's format, target, size, num_levels, etc.
     */
    if (stObj->pt) {
-      const enum pipe_format fmt =
-         st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
       if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
-          stObj->pt->format != fmt ||
+          stObj->pt->format != firstImageFormat ||
           stObj->pt->last_level < stObj->lastLevel ||
-          stObj->pt->width[0] != firstImage->base.Width2 ||
-          stObj->pt->height[0] != firstImage->base.Height2 ||
-          stObj->pt->depth[0] != firstImage->base.Depth2 ||
-          stObj->pt->block.size != blockSize)
+          stObj->pt->width0 != stObj->width0 ||
+          stObj->pt->height0 != stObj->height0 ||
+          stObj->pt->depth0 != stObj->depth0)
       {
-         pipe_texture_reference(&stObj->pt, NULL);
-         ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
+         /* The gallium texture does not match the Mesa texture so delete the
+          * gallium texture now.  We'll make a new one below.
+          */
+         pipe_resource_reference(&stObj->pt, NULL);
+         pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+         st->dirty.st |= ST_NEW_FRAMEBUFFER;
       }
    }
 
    /* May need to create a new gallium texture:
     */
    if (!stObj->pt) {
-      const enum pipe_format fmt =
-         st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
-      GLuint usage = default_usage(fmt);
+      GLuint bindings = default_bindings(st, firstImageFormat);
 
-      stObj->pt = st_texture_create(ctx->st,
+      stObj->pt = st_texture_create(st,
                                     gl_target_to_pipe(stObj->base.Target),
-                                    fmt,
+                                    firstImageFormat,
                                     stObj->lastLevel,
-                                    firstImage->base.Width2,
-                                    firstImage->base.Height2,
-                                    firstImage->base.Depth2,
-                                    usage);
+                                    stObj->width0,
+                                    stObj->height0,
+                                    stObj->depth0,
+                                    bindings);
 
       if (!stObj->pt) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
@@ -1827,15 +1877,14 @@ st_finalize_texture(GLcontext *ctx,
     */
    for (face = 0; face < nr_faces; face++) {
       GLuint level;
-      for (level = 0; level <= stObj->lastLevel; level++) {
+      for (level = stObj->base.BaseLevel; level <= stObj->lastLevel; level++) {
          struct st_texture_image *stImage =
-            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
+            st_texture_image(stObj->base.Image[face][level]);
 
          /* Need to import images in main memory or held in other textures.
           */
          if (stImage && stObj->pt != stImage->pt) {
-            copy_image_data_to_texture(ctx->st, stObj, level, stImage);
-           *needFlush = GL_TRUE;
+            copy_image_data_to_texture(st, stObj, level, stImage);
          }
       }
    }