[Mesa-dev] [PATCH v5] i965: Fix ETC2/EAC GetCompressed* functions on Gen7 GPUs

Nanley Chery nanleychery at gmail.com
Thu Jun 14 19:27:06 UTC 2018


On Thu, Jun 07, 2018 at 09:34:41AM +0300, Eleni Maria Stea wrote:
> Gen 7 GPUs store the compressed EAC/ETC2 images in other non-compressed
> formats that can render. When GetCompressed* functions are called, the
> pixels are returned in the non-compressed format that is used for the
> rendering.
> 
> With this patch we store both the compressed and non-compressed versions
> of the image, so that both rendering commands and GetCompressed*
> commands work.
> 
> Also, the assertions for GL_MAP_WRITE_BIT and GL_MAP_INVALIDATE_RANGE_BIT
> in intel_miptree_map_etc function have been removed because when the
> miptree is mapped for reading (for example from a GetCompress*
> function) the GL_MAP_WRITE_BIT won't be set (and shouldn't be set).
> 
> Fixes: the following test in CTS for gen7:
> KHR-GL45.direct_state_access.textures_compressed_subimage test
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104272
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=81843
> 
> v2: fixes issues:
>    a) initialized uninitialized variables (Juan A. Suarez, Andres Gomez)
>    b) fixed race condition where mt and cmt were mapped at the same time
>    c) fixed indentation issues (Andres Gomez)
> v3: adds bugzilla bug with id: 104272
> v4: adds bugzilla bug with id: 81843
> v5: replaced the flags with a bitfield, refactoring (Kenneth Graunke)

+Jason, Ken

Hello,

I recently did some miptree work relating to the r8stencil_mt and I
think I now have a more informed opinion about how things should be
structured. I'd like to propose an alternative solution.

I had initially thought we should have a separate miptree to hold the
compressed data, like this patch does, but now I think we should
actually have the compressed data be the main miptree and to store the
decompressed miptree as part of the main one. The reasoning is that we
could reuse this structure to handle the r8stencil workaround and to
eventually handle the ASTC_LDR surfaces that are modified on gen9.

I'm proposing something like the following:

1. Rename r8stencil_mt ->shadow_mt and
   r8stencil_needs_update -> shadow_needs_update.
2. Make shadow_mt hold the decompressed ETC miptree
3. Update shadow_needs_update whenever the main mt is modified
4. Add an function to update the shadow_mt using the main mt as a source
5. Sample from the shadow_mt as appropriate
6. Make the main miptree hold the compressed data

This method should also be able to handle the CopyImage functions. What
do you all think?

-Nanley

> ---
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.c |  10 +-
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.h |  10 ++
>  src/mesa/drivers/dri/i965/intel_tex.c         | 106 +++++++++++++++---
>  src/mesa/drivers/dri/i965/intel_tex.h         |   1 -
>  src/mesa/drivers/dri/i965/intel_tex_image.c   |  46 +++++++-
>  src/mesa/drivers/dri/i965/intel_tex_obj.h     |   8 ++
>  src/mesa/main/texstore.c                      |  51 ++++++---
>  src/mesa/main/texstore.h                      |   8 +-
>  8 files changed, 197 insertions(+), 43 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> index 7d1fa96b91..cc807977de 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> @@ -733,9 +733,10 @@ miptree_create(struct brw_context *brw,
>     mesa_format etc_format = MESA_FORMAT_NONE;
>     uint32_t alloc_flags = 0;
>  
> -   format = intel_lower_compressed_format(brw, format);
> -
> -   etc_format = (format != tex_format) ? tex_format : MESA_FORMAT_NONE;
> +   if (!(flags & MIPTREE_CREATE_ETC)) {
> +      format = intel_lower_compressed_format(brw, format);
> +      etc_format = (format != tex_format) ? tex_format : MESA_FORMAT_NONE;
> +   }
>  
>     if (flags & MIPTREE_CREATE_BUSY)
>        alloc_flags |= BO_ALLOC_BUSY;
> @@ -3372,9 +3373,6 @@ intel_miptree_map_etc(struct brw_context *brw,
>        assert(mt->format == MESA_FORMAT_R8G8B8X8_UNORM);
>     }
>  
> -   assert(map->mode & GL_MAP_WRITE_BIT);
> -   assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT);
> -
>     intel_miptree_access_raw(brw, mt, level, slice, true);
>  
>     map->stride = _mesa_format_row_stride(mt->etc_format, map->w);
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> index 42f73ba1f9..9e7a401229 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> @@ -74,6 +74,7 @@ struct intel_texture_image;
>   * without transcoding back.  This flag to intel_miptree_map() gets you that.
>   */
>  #define BRW_MAP_DIRECT_BIT	0x80000000
> +#define BRW_MAP_ETC_BIT	0x40000000
>  
>  struct intel_miptree_map {
>     /** Bitfield of GL_MAP_*_BIT and BRW_MAP_*_BIT. */
> @@ -380,6 +381,15 @@ enum intel_miptree_create_flags {
>      * that the miptree will be created with mt->aux_usage == NONE.
>      */
>     MIPTREE_CREATE_NO_AUX   = 1 << 2,
> +
> +   /** Create a second miptree for the compressed pixels (Gen7 only)
> +    *
> +    * On Gen7, we need to store 2 miptrees for some compressed
> +    * formats so we can handle rendering as well as getting the
> +    * compressed image data. This flag indicates that the miptree
> +    * is expected to hold compressed data for the latter case.
> +    */
> +   MIPTREE_CREATE_ETC      = 1 << 3,
>  };
>  
>  struct intel_mipmap_tree *intel_miptree_create(struct brw_context *brw,
> diff --git a/src/mesa/drivers/dri/i965/intel_tex.c b/src/mesa/drivers/dri/i965/intel_tex.c
> index 0650b6e629..3a94fa7477 100644
> --- a/src/mesa/drivers/dri/i965/intel_tex.c
> +++ b/src/mesa/drivers/dri/i965/intel_tex.c
> @@ -66,6 +66,8 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
>     struct intel_texture_image *intel_image = intel_texture_image(image);
>     struct gl_texture_object *texobj = image->TexObject;
>     struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
> +   struct gen_device_info *devinfo = &brw->screen->devinfo;
> +   mesa_format fmt = image->TexFormat;
>  
>     assert(image->Border == 0);
>  
> @@ -110,6 +112,33 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
>            image->Width, image->Height, image->Depth, intel_image->mt);
>     }
>  
> +   if (devinfo->gen < 8 && _mesa_is_format_etc2(fmt)) {
> +      if (intel_texobj->cmt &&
> +          intel_miptree_match_image(intel_texobj->cmt, image)) {
> +         intel_miptree_reference(&intel_image->cmt, intel_texobj->cmt);
> +         DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
> +             __func__, texobj, image->Level,
> +             image->Width, image->Height, image->Depth, intel_texobj->cmt);
> +      } else {
> +         intel_image->cmt = intel_miptree_create_for_teximage(brw,
> +                                                              intel_texobj,
> +                                                              intel_image,
> +                                                              MIPTREE_CREATE_ETC);
> +         if (!intel_image->cmt)
> +            return false;
> +
> +         /* Even if the object currently has a mipmap tree associated
> +          * with it, this one is a more likely candidate to represent the
> +          * whole object since our level didn't fit what was there
> +          * before, and any lower levels would fit into our miptree.
> +          */
> +         intel_miptree_reference(&intel_texobj->cmt, intel_image->cmt);
> +
> +         DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
> +             __func__, texobj, image->Level,
> +             image->Width, image->Height, image->Depth, intel_image->cmt);
> +      }
> +   }
>     intel_texobj->needs_validate = true;
>  
>     return true;
> @@ -128,6 +157,7 @@ intel_alloc_texture_storage(struct gl_context *ctx,
>                              GLsizei height, GLsizei depth)
>  {
>     struct brw_context *brw = brw_context(ctx);
> +   struct gen_device_info *devinfo = &brw->screen->devinfo;
>     struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
>     struct gl_texture_image *first_image = texobj->Image[0][0];
>     int num_samples = intel_quantize_num_samples(brw->screen,
> @@ -136,6 +166,9 @@ intel_alloc_texture_storage(struct gl_context *ctx,
>     int face;
>     int level;
>  
> +   mesa_format fmt = first_image->TexFormat;
> +   bool is_fake_etc = (devinfo->gen < 8) && _mesa_is_format_etc2(fmt);
> +
>     /* If the object's current miptree doesn't match what we need, make a new
>      * one.
>      */
> @@ -157,6 +190,22 @@ intel_alloc_texture_storage(struct gl_context *ctx,
>        }
>     }
>  
> +   if (is_fake_etc) {
> +      if (!intel_texobj->cmt ||
> +          !intel_miptree_match_image(intel_texobj->cmt, first_image) ||
> +          intel_texobj->cmt->last_level != levels - 1) {
> +         intel_miptree_release(&intel_texobj->cmt);
> +
> +         intel_get_image_dims(first_image, &width, &height, &depth);
> +         intel_texobj->cmt = intel_miptree_create(brw, texobj->Target,
> +                                                  first_image->TexFormat,
> +                                                  0, levels - 1,
> +                                                  width, height, depth,
> +                                                  MAX2(num_samples, 1),
> +                                                  MIPTREE_CREATE_ETC);
> +      }
> +   }
> +
>     for (face = 0; face < numFaces; face++) {
>        for (level = 0; level < levels; level++) {
>           struct gl_texture_image *image = texobj->Image[face][level];
> @@ -169,6 +218,8 @@ intel_alloc_texture_storage(struct gl_context *ctx,
>              return false;
>  
>           intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
> +         if (is_fake_etc)
> +            intel_miptree_reference(&intel_image->cmt, intel_texobj->cmt);
>        }
>     }
>  
> @@ -181,7 +232,6 @@ intel_alloc_texture_storage(struct gl_context *ctx,
>     return true;
>  }
>  
> -
>  static void
>  intel_free_texture_image_buffer(struct gl_context * ctx,
>  				struct gl_texture_image *texImage)
> @@ -191,6 +241,7 @@ intel_free_texture_image_buffer(struct gl_context * ctx,
>     DBG("%s\n", __func__);
>  
>     intel_miptree_release(&intelImage->mt);
> +   intel_miptree_release(&intelImage->cmt);
>  
>     _swrast_free_texture_image_buffer(ctx, texImage);
>  }
> @@ -204,37 +255,52 @@ intel_free_texture_image_buffer(struct gl_context * ctx,
>   */
>  static void
>  intel_map_texture_image(struct gl_context *ctx,
> -			struct gl_texture_image *tex_image,
> -			GLuint slice,
> -			GLuint x, GLuint y, GLuint w, GLuint h,
> -			GLbitfield mode,
> -			GLubyte **map,
> -			GLint *out_stride)
> +                        struct gl_texture_image *tex_image,
> +                        GLuint slice,
> +                        GLuint x, GLuint y, GLuint w, GLuint h,
> +                        GLbitfield mode,
> +                        GLubyte **map,
> +                        GLint *out_stride)
>  {
>     struct brw_context *brw = brw_context(ctx);
> +   struct gen_device_info *devinfo = &brw->screen->devinfo;
> +   mesa_format fmt = tex_image->TexFormat;
>     struct intel_texture_image *intel_image = intel_texture_image(tex_image);
>     struct intel_mipmap_tree *mt = intel_image->mt;
> +   struct intel_mipmap_tree *cmt = intel_image->cmt;
>     ptrdiff_t stride;
>  
>     /* Our texture data is always stored in a miptree. */
>     assert(mt);
>  
>     /* Check that our caller wasn't confused about how to map a 1D texture. */
> -   assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
> -	  h == 1);
> +   assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || h == 1);
>  
> -   /* intel_miptree_map operates on a unified "slice" number that references the
> -    * cube face, since it's all just slices to the miptree code.
> +   /* intel_miptree_map operates on a unified "slice" number that references
> +    * the cube face, since it's all just slices to the miptree code.
>      */
>     if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
>        slice = tex_image->Face;
>  
> +   if (devinfo->gen < 8) {
> +      if ((!(mode & GL_MAP_WRITE_BIT) && _mesa_is_format_etc2(fmt)) ||
> +            (mode & BRW_MAP_ETC_BIT)) {
> +            assert(cmt);
> +            intel_miptree_map(brw, cmt,
> +                              tex_image->Level + tex_image->TexObject->MinLevel,
> +                              slice + tex_image->TexObject->MinLayer,
> +                              x, y, w, h, mode,
> +                              (void **)map, &stride);
> +            *out_stride = stride;
> +            return;
> +      }
> +   }
> +
>     intel_miptree_map(brw, mt,
>                       tex_image->Level + tex_image->TexObject->MinLevel,
>                       slice + tex_image->TexObject->MinLayer,
>                       x, y, w, h, mode,
>                       (void **)map, &stride);
> -
>     *out_stride = stride;
>  }
>  
> @@ -243,15 +309,25 @@ intel_unmap_texture_image(struct gl_context *ctx,
>  			  struct gl_texture_image *tex_image, GLuint slice)
>  {
>     struct brw_context *brw = brw_context(ctx);
> +
>     struct intel_texture_image *intel_image = intel_texture_image(tex_image);
>     struct intel_mipmap_tree *mt = intel_image->mt;
> +   struct intel_mipmap_tree *cmt = intel_image->cmt;
>  
>     if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
>        slice = tex_image->Face;
>  
> -   intel_miptree_unmap(brw, mt,
> -         tex_image->Level + tex_image->TexObject->MinLevel,
> -         slice + tex_image->TexObject->MinLayer);
> +   if (cmt) {
> +      intel_miptree_unmap(brw, cmt,
> +                          tex_image->Level + tex_image->TexObject->MinLevel,
> +                          slice + tex_image->TexObject->MinLayer);
> +   }
> +
> +   if (mt) {
> +      intel_miptree_unmap(brw, mt,
> +                          tex_image->Level + tex_image->TexObject->MinLevel,
> +                          slice + tex_image->TexObject->MinLayer);
> +   }
>  }
>  
>  static GLboolean
> diff --git a/src/mesa/drivers/dri/i965/intel_tex.h b/src/mesa/drivers/dri/i965/intel_tex.h
> index 4c48875f82..1131ea6009 100644
> --- a/src/mesa/drivers/dri/i965/intel_tex.h
> +++ b/src/mesa/drivers/dri/i965/intel_tex.h
> @@ -54,5 +54,4 @@ intel_miptree_create_for_teximage(struct brw_context *brw,
>  
>  void intel_finalize_mipmap_tree(struct brw_context *brw,
>                                  struct gl_texture_object *tex_obj);
> -
>  #endif
> diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
> index fae179214d..5cb8adcb7e 100644
> --- a/src/mesa/drivers/dri/i965/intel_tex_image.c
> +++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
> @@ -860,7 +860,7 @@ flush_astc_denorms(struct gl_context *ctx, GLuint dims,
>     for (int slice = 0; slice < store.CopySlices; slice++) {
>  
>        /* Map dest texture buffer */
> -      GLubyte *dstMap;
> +      GLubyte *dstMap = NULL;
>        GLint dstRowStride;
>        ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset,
>                                    xoffset, yoffset, width, height,
> @@ -904,6 +904,48 @@ flush_astc_denorms(struct gl_context *ctx, GLuint dims,
>     }
>  }
>  
> +static void
> +intel_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
> +                                   struct gl_texture_image *intelImage,
> +                                   GLint xoffset, GLint yoffset, GLint zoffset,
> +                                   GLsizei width, GLsizei height,
> +                                   GLsizei depth, GLenum format,
> +                                   GLsizei imageSize, const GLvoid *data)
> +{
> +   struct compressed_pixelstore store;
> +   struct brw_context *brw = (struct brw_context*) ctx;
> +   const struct gen_device_info *devinfo = &brw->screen->devinfo;
> +   GLbitfield mode = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
> +
> +   if (dims == 1) {
> +      _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call");
> +      return;
> +   }
> +
> +   _mesa_compute_compressed_pixelstore(dims, intelImage->TexFormat,
> +                                       width, height, depth,
> +                                       &ctx->Unpack, &store);
> +
> +   /* Get pointer to src pixels (may be in a pbo which we'll map here) */
> +   data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data,
> +                                                 &ctx->Unpack,
> +                                                 "glCompressedTexSubImage");
> +   if (!data)
> +      return;
> +
> +   _mesa_upload_compressed_texsubimage(ctx, dims, &store, intelImage,
> +                                       xoffset, yoffset, zoffset,
> +                                       width, height, mode, data);
> +
> +   if ((devinfo->gen < 8) && _mesa_is_format_etc2(intelImage->TexFormat)) {
> +      _mesa_upload_compressed_texsubimage(ctx, dims, &store, intelImage,
> +                                          xoffset, yoffset, zoffset,
> +                                          width, height,
> +                                          mode | BRW_MAP_ETC_BIT, data);
> +   }
> +
> +   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
> +}
>  
>  static void
>  intelCompressedTexSubImage(struct gl_context *ctx, GLuint dims,
> @@ -914,7 +956,7 @@ intelCompressedTexSubImage(struct gl_context *ctx, GLuint dims,
>                          GLsizei imageSize, const GLvoid *data)
>  {
>     /* Upload the compressed data blocks */
> -   _mesa_store_compressed_texsubimage(ctx, dims, texImage,
> +   intel_store_compressed_texsubimage(ctx, dims, texImage,
>                                        xoffset, yoffset, zoffset,
>                                        width, height, depth,
>                                        format, imageSize, data);
> diff --git a/src/mesa/drivers/dri/i965/intel_tex_obj.h b/src/mesa/drivers/dri/i965/intel_tex_obj.h
> index 526f5ceb47..ce4b7a0d36 100644
> --- a/src/mesa/drivers/dri/i965/intel_tex_obj.h
> +++ b/src/mesa/drivers/dri/i965/intel_tex_obj.h
> @@ -50,6 +50,11 @@ struct intel_texture_object
>      */
>     struct intel_mipmap_tree *mt;
>  
> +   /* This miptree is used to store the compressed ETC2/EAC pixels
> +    * on Gen 7 GPUs for GetCompressed* functions to work.
> +    */
> +   struct intel_mipmap_tree *cmt;
> +
>     /**
>      * Set when mipmap trees in the texture images of this texture object
>      * might not all be the mipmap tree above.
> @@ -79,6 +84,9 @@ struct intel_texture_image
>      * Else there is no image data.
>      */
>     struct intel_mipmap_tree *mt;
> +
> +   /* Stores the ETC2 formatted image on Gen7 GPUs */
> +   struct intel_mipmap_tree *cmt;
>  };
>  
>  static inline struct intel_texture_object *
> diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
> index 31163f6771..b441e15852 100644
> --- a/src/mesa/main/texstore.c
> +++ b/src/mesa/main/texstore.c
> @@ -1328,10 +1328,7 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
>                                     GLsizei imageSize, const GLvoid *data)
>  {
>     struct compressed_pixelstore store;
> -   GLint dstRowStride;
> -   GLint i, slice;
> -   GLubyte *dstMap;
> -   const GLubyte *src;
> +   GLbitfield mode = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
>  
>     if (dims == 1) {
>        _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call");
> @@ -1349,41 +1346,59 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
>     if (!data)
>        return;
>  
> -   src = (const GLubyte *) data + store.SkipBytes;
> +   _mesa_upload_compressed_texsubimage(ctx, dims, &store, texImage,
> +                                       xoffset, yoffset, zoffset,
> +                                       width, height, mode, data);
>  
> -   for (slice = 0; slice < store.CopySlices; slice++) {
> +   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
> +}
> +
> +void
> +_mesa_upload_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
> +                                    struct compressed_pixelstore *store,
> +                                    struct gl_texture_image *texImage,
> +                                    GLint xoffset, GLint yoffset, GLint zoffset,
> +                                    GLsizei width, GLsizei height,
> +                                    GLbitfield mode, const GLvoid *data)
> +{
> +   GLint i, slice, dstRowStride;
> +   GLubyte *dstMap = NULL;
> +
> +   if (!data)
> +      return;
> +
> +   const GLubyte *src = (const GLubyte *) data + store->SkipBytes;
> +
> +   for (slice = 0; slice < store->CopySlices; slice++) {
>        /* Map dest texture buffer */
>        ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset,
>                                    xoffset, yoffset, width, height,
> -                                  GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
> +                                  mode,
>                                    &dstMap, &dstRowStride);
>  
>        if (dstMap) {
> -
>           /* copy rows of blocks */
> -         if (dstRowStride == store.TotalBytesPerRow &&
> -             dstRowStride == store.CopyBytesPerRow) {
> -            memcpy(dstMap, src, store.CopyBytesPerRow * store.CopyRowsPerSlice);
> -            src += store.CopyBytesPerRow * store.CopyRowsPerSlice;
> +         if (dstRowStride == store->TotalBytesPerRow &&
> +             dstRowStride == store->CopyBytesPerRow) {
> +            memcpy(dstMap, src, store->CopyBytesPerRow * store->CopyRowsPerSlice);
> +            src += store->CopyBytesPerRow * store->CopyRowsPerSlice;
>           }
>           else {
> -            for (i = 0; i < store.CopyRowsPerSlice; i++) {
> -               memcpy(dstMap, src, store.CopyBytesPerRow);
> +            for (i = 0; i < store->CopyRowsPerSlice; i++) {
> +               memcpy(dstMap, src, store->CopyBytesPerRow);
>                 dstMap += dstRowStride;
> -               src += store.TotalBytesPerRow;
> +               src += store->TotalBytesPerRow;
>              }
>           }
>  
>           ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset);
>  
>           /* advance to next slice */
> -         src += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice);
> +         src += store->TotalBytesPerRow * (store->TotalRowsPerSlice - store->CopyRowsPerSlice);
>        }
>        else {
>           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD",
>                       dims);
>        }
>     }
> -
> -   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
>  }
> diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h
> index 2fef7ba7d7..4b197e1641 100644
> --- a/src/mesa/main/texstore.h
> +++ b/src/mesa/main/texstore.h
> @@ -148,7 +148,6 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
>                                     GLenum format,
>                                     GLsizei imageSize, const GLvoid *data);
>  
> -
>  struct compressed_pixelstore {
>     int SkipBytes;
>     int CopyBytesPerRow;
> @@ -158,6 +157,13 @@ struct compressed_pixelstore {
>     int CopySlices;
>  };
>  
> +extern void
> +_mesa_upload_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
> +                                    struct compressed_pixelstore *store,
> +                                    struct gl_texture_image *texImage,
> +                                    GLint xoffset, GLint yoffset, GLint zoffset,
> +                                    GLsizei width, GLsizei height,
> +                                    GLbitfield mode, const GLvoid *data);
>  
>  extern void
>  _mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
> -- 
> 2.17.0
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list