st/mesa: properly implement MapTextureImage with multiple mapped slices (v2)
[mesa.git] / src / mesa / state_tracker / st_cb_texture.c
index 81a5d9b4dfbb1f2e0f28df69a146c1c815b5a3e8..97bba8b7da59f38c663f8c7462269da3e99121d5 100644 (file)
@@ -151,13 +151,11 @@ static void
 st_DeleteTextureObject(struct gl_context *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_resource_reference(&stObj->pt, NULL);
-   if (stObj->sampler_view) {
-      pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
-   }
+
+   pipe_resource_reference(&stObj->pt, NULL);
+   st_texture_release_all_sampler_views(stObj);
+   st_texture_free_sampler_views(stObj);
    _mesa_delete_texture_object(ctx, texObj);
 }
 
@@ -177,6 +175,10 @@ st_FreeTextureImageBuffer(struct gl_context *ctx,
 
    _mesa_align_free(stImage->TexData);
    stImage->TexData = NULL;
+
+   free(stImage->transfer);
+   stImage->transfer = NULL;
+   stImage->num_transfers = 0;
 }
 
 
@@ -192,6 +194,7 @@ st_MapTextureImage(struct gl_context *ctx,
    struct st_texture_image *stImage = st_texture_image(texImage);
    unsigned pipeMode;
    GLubyte *map;
+   struct pipe_transfer *transfer;
 
    pipeMode = 0x0;
    if (mode & GL_MAP_READ_BIT)
@@ -201,10 +204,11 @@ st_MapTextureImage(struct gl_context *ctx,
    if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
       pipeMode |= PIPE_TRANSFER_DISCARD_RANGE;
 
-   map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1);
+   map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1,
+                              &transfer);
    if (map) {
       *mapOut = map;
-      *rowStrideOut = stImage->transfer->stride;
+      *rowStrideOut = transfer->stride;
    }
    else {
       *mapOut = NULL;
@@ -221,7 +225,7 @@ st_UnmapTextureImage(struct gl_context *ctx,
 {
    struct st_context *st = st_context(ctx);
    struct st_texture_image *stImage  = st_texture_image(texImage);
-   st_texture_image_unmap(st, stImage);
+   st_texture_image_unmap(st, stImage, slice);
 }
 
 
@@ -454,7 +458,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
    /* The parent texture object does not have space for this image */
 
    pipe_resource_reference(&stObj->pt, NULL);
-   pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+   st_texture_release_all_sampler_views(stObj);
 
    if (!guess_and_alloc_texture(st, stObj, stImage)) {
       /* Probably out of memory.
@@ -865,7 +869,9 @@ st_GetTexImage(struct gl_context * ctx,
    ubyte *map = NULL;
    boolean done = FALSE;
 
-   if (!st->prefer_blit_based_texture_transfer) {
+   if (!st->prefer_blit_based_texture_transfer &&
+       !_mesa_is_format_compressed(texImage->TexFormat)) {
+      /* Try to avoid the fallback if we're doing texture decompression here */
       goto fallback;
    }
 
@@ -1144,6 +1150,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
    unsigned dst_width = width;
    unsigned dst_height = height;
    unsigned dst_depth = 1;
+   struct pipe_transfer *transfer;
 
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
@@ -1169,7 +1176,8 @@ fallback_copy_texsubimage(struct gl_context *ctx,
 
    texDest = st_texture_image_map(st, stImage, transfer_usage,
                                   destX, destY, slice,
-                                  dst_width, dst_height, dst_depth);
+                                  dst_width, dst_height, dst_depth,
+                                  &transfer);
 
    if (baseFormat == GL_DEPTH_COMPONENT ||
        baseFormat == GL_DEPTH_STENCIL) {
@@ -1199,13 +1207,11 @@ fallback_copy_texsubimage(struct gl_context *ctx,
             }
 
             if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) {
-               pipe_put_tile_z(stImage->transfer,
-                               texDest + row*stImage->transfer->layer_stride,
+               pipe_put_tile_z(transfer, texDest + row*transfer->layer_stride,
                                0, 0, width, 1, data);
             }
             else {
-               pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1,
-                               data);
+               pipe_put_tile_z(transfer, texDest, 0, row, width, 1, data);
             }
          }
       }
@@ -1231,10 +1237,10 @@ fallback_copy_texsubimage(struct gl_context *ctx,
          }
 
          if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) {
-            dstRowStride = stImage->transfer->layer_stride;
+            dstRowStride = transfer->layer_stride;
          }
          else {
-            dstRowStride = stImage->transfer->stride;
+            dstRowStride = transfer->stride;
          }
 
          /* get float/RGBA image from framebuffer */
@@ -1267,7 +1273,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
       free(tempSrc);
    }
 
-   st_texture_image_unmap(st, stImage);
+   st_texture_image_unmap(st, stImage, slice);
    pipe->transfer_unmap(pipe, src_trans);
 }
 
@@ -1483,9 +1489,15 @@ st_finalize_texture(struct gl_context *ctx,
    if (tObj->Target == GL_TEXTURE_BUFFER) {
       struct st_buffer_object *st_obj = st_buffer_object(tObj->BufferObject);
 
+      if (!st_obj) {
+         pipe_resource_reference(&stObj->pt, NULL);
+         st_texture_release_all_sampler_views(stObj);
+         return GL_TRUE;
+      }
+
       if (st_obj->buffer != stObj->pt) {
          pipe_resource_reference(&stObj->pt, st_obj->buffer);
-         pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+         st_texture_release_all_sampler_views(stObj);
          stObj->width0 = stObj->pt->width0 / _mesa_get_format_bytes(tObj->_BufferObjectFormat);
          stObj->height0 = 1;
          stObj->depth0 = 1;
@@ -1506,7 +1518,7 @@ st_finalize_texture(struct gl_context *ctx,
        firstImage->pt != stObj->pt &&
        (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) {
       pipe_resource_reference(&stObj->pt, firstImage->pt);
-      pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+      st_texture_release_all_sampler_views(stObj);
    }
 
    /* If this texture comes from a window system, there is nothing else to do. */
@@ -1553,7 +1565,7 @@ st_finalize_texture(struct gl_context *ctx,
           * gallium texture now.  We'll make a new one below.
           */
          pipe_resource_reference(&stObj->pt, NULL);
-         pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+         st_texture_release_all_sampler_views(stObj);
          st->dirty.st |= ST_NEW_FRAMEBUFFER;
       }
    }