[Mesa-dev] [PATCH 2/5] st/mesa: add support for ETC2 formats

Glenn Kennard glenn.kennard at gmail.com
Sun Aug 3 09:23:30 PDT 2014


On Sun, 03 Aug 2014 14:40:37 +0200, Marek Olšák <maraeo at gmail.com> wrote:

> From: Marek Olšák <marek.olsak at amd.com>
>
> The formats are emulated by translating them into plain uncompressed
> formats, because I don't know of any hardware which supports them.
>
> This is required for GLES 3.0 and ARB_ES3_compatibility (GL 4.3).
> ---
>  src/mesa/state_tracker/st_cb_texture.c | 54  
> ++++++++++++++++++++++++++++++++--
>  src/mesa/state_tracker/st_format.c     | 24 +++++++++++++++
>  src/mesa/state_tracker/st_texture.c    | 11 +++----
>  src/mesa/state_tracker/st_texture.h    | 12 +++++++-
>  4 files changed, 93 insertions(+), 8 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_cb_texture.c  
> b/src/mesa/state_tracker/st_cb_texture.c
> index aa6b05f..88c4b25 100644
> --- a/src/mesa/state_tracker/st_cb_texture.c
> +++ b/src/mesa/state_tracker/st_cb_texture.c
> @@ -37,6 +37,7 @@
>  #include "main/pbo.h"
>  #include "main/pixeltransfer.h"
>  #include "main/texcompress.h"
> +#include "main/texcompress_etc.h"
>  #include "main/texgetimage.h"
>  #include "main/teximage.h"
>  #include "main/texobj.h"
> @@ -207,8 +208,31 @@ st_MapTextureImage(struct gl_context *ctx,
>     map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h,  
> 1,
>                                &transfer);
>     if (map) {
> -      *mapOut = map;
> -      *rowStrideOut = transfer->stride;
> +      if (_mesa_is_format_etc2(texImage->TexFormat)) {
> +         /* ETC isn't supported by gallium and it's represented

Freedreno could definitely support it natively, at least for a3xx. Though  
it can cross that bridge once it gets there i suppose.

> +          * by uncompressed formats. Only write transfers with  
> precompressed
> +          * data are supported by ES3, which makes this really simple.
> +          *
> +          * Just create a temporary storage where the ETC texture will
> +          * be stored. It will be decompressed in the Unmap function.
> +          */

Question: Is it possible to create a permanent map of a texture in GL?

> +         unsigned z = transfer->box.z;

Nitpick: transfer->box.z is a signed int.

> +         struct st_texture_image_transfer *itransfer =  
> &stImage->transfer[z];
> +
> +         itransfer->temp_data =
> +            malloc(_mesa_format_image_size(texImage->TexFormat, w, h,  
> 1));
> +         itransfer->temp_stride =
> +            _mesa_format_row_stride(texImage->TexFormat, w);
> +         itransfer->map = map;
> +
> +         *mapOut = itransfer->temp_data;
> +         *rowStrideOut = itransfer->temp_stride;
> +      }
> +      else {
> +         /* supported mapping */
> +         *mapOut = map;
> +         *rowStrideOut = transfer->stride;
> +      }
>     }
>     else {
>        *mapOut = NULL;
> @@ -225,6 +249,26 @@ st_UnmapTextureImage(struct gl_context *ctx,
>  {
>     struct st_context *st = st_context(ctx);
>     struct st_texture_image *stImage  = st_texture_image(texImage);
> +
> +   if (_mesa_is_format_etc2(texImage->TexFormat)) {
> +      /* Decompress the ETC texture to the mapped one. */
> +      unsigned z = slice + stImage->base.Face;

int

> +      struct st_texture_image_transfer *itransfer =  
> &stImage->transfer[z];
> +      struct pipe_transfer *transfer = itransfer->transfer;
> +
> +      assert(z == transfer->box.z);
> +
> +      _mesa_unpack_etc2_format(itransfer->map, transfer->stride,
> +                               itransfer->temp_data,  
> itransfer->temp_stride,
> +                               transfer->box.width,  
> transfer->box.height,
> +                               texImage->TexFormat);

Is the ETC source data always an integer number of blocks?

> +
> +      free(itransfer->temp_data);
> +      itransfer->temp_data = NULL;
> +      itransfer->temp_stride = 0;
> +      itransfer->map = 0;
> +   }
> +
>     st_texture_image_unmap(st, stImage, slice);
>  }
> @@ -613,6 +657,8 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
>     unsigned bind;
>     GLubyte *map;
> +   assert(!_mesa_is_format_etc2(texImage->TexFormat));
> +
>     if (!st->prefer_blit_based_texture_transfer) {
>        goto fallback;
>     }
> @@ -870,6 +916,8 @@ st_GetTexImage(struct gl_context * ctx,
>     ubyte *map = NULL;
>     boolean done = FALSE;
> +   assert(!_mesa_is_format_etc2(texImage->TexFormat));
> +
>     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 */
> @@ -1306,6 +1354,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint  
> dims,
>     unsigned bind;
>     GLint srcY0, srcY1;
> +   assert(!_mesa_is_format_etc2(texImage->TexFormat));
> +
>     if (!strb || !strb->surface || !stImage->pt) {
>        debug_printf("%s: null strb or stImage\n", __FUNCTION__);
>        return;
> diff --git a/src/mesa/state_tracker/st_format.c  
> b/src/mesa/state_tracker/st_format.c
> index 409079b..ff3f494 100644
> --- a/src/mesa/state_tracker/st_format.c
> +++ b/src/mesa/state_tracker/st_format.c
> @@ -402,6 +402,26 @@ st_mesa_format_to_pipe_format(mesa_format  
> mesaFormat)
>     case MESA_FORMAT_B8G8R8X8_SRGB:
>        return PIPE_FORMAT_B8G8R8X8_SRGB;
> +   /* ETC2 formats are emulated as uncompressed ones.
> +    * The destination formats mustn't be changed, because they are also
> +    * destination formats of the unpack/decompression function. */
> +   case MESA_FORMAT_ETC2_RGB8:
> +   case MESA_FORMAT_ETC2_RGBA8_EAC:
> +   case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
> +      return PIPE_FORMAT_R8G8B8A8_UNORM;
> +   case MESA_FORMAT_ETC2_SRGB8:
> +   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
> +   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
> +      return PIPE_FORMAT_B8G8R8A8_SRGB;
> +   case MESA_FORMAT_ETC2_R11_EAC:
> +      return PIPE_FORMAT_R16_UNORM;
> +   case MESA_FORMAT_ETC2_RG11_EAC:
> +      return PIPE_FORMAT_R16G16_UNORM;
> +   case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
> +      return PIPE_FORMAT_R16_SNORM;
> +   case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
> +      return PIPE_FORMAT_R16G16_SNORM;
> +
>     default:
>        return PIPE_FORMAT_NONE;
>     }
> @@ -781,6 +801,10 @@ test_format_conversion(void)
>    /* test all Mesa formats */
>     for (i = 1; i < MESA_FORMAT_COUNT; i++) {
> +      /* ETC2 formats are translated differently, skip them. */
> +      if (_mesa_is_format_etc2(i))
> +         continue;
> +
>        enum pipe_format pf = st_mesa_format_to_pipe_format(i);
>        if (pf != PIPE_FORMAT_NONE) {
>           mesa_format mf = st_pipe_format_to_mesa_format(pf);
> diff --git a/src/mesa/state_tracker/st_texture.c  
> b/src/mesa/state_tracker/st_texture.c
> index c148821..9f57cfb 100644
> --- a/src/mesa/state_tracker/st_texture.c
> +++ b/src/mesa/state_tracker/st_texture.c
> @@ -269,14 +269,15 @@ st_texture_image_map(struct st_context *st, struct  
> st_texture_image *stImage,
>           unsigned new_size = z + 1;
>          stImage->transfer = realloc(stImage->transfer,
> -                                     new_size * sizeof(void*));
> +                     new_size * sizeof(struct  
> st_texture_image_transfer));
>           memset(&stImage->transfer[stImage->num_transfers], 0,
> -               (new_size - stImage->num_transfers) * sizeof(void*));
> +                (new_size - stImage->num_transfers) *
> +                sizeof(struct st_texture_image_transfer));
>           stImage->num_transfers = new_size;
>        }
> -      assert(!stImage->transfer[z]);
> -      stImage->transfer[z] = *transfer;
> +      assert(!stImage->transfer[z].transfer);
> +      stImage->transfer[z].transfer = *transfer;
>     }
>     return map;
>  }
> @@ -288,7 +289,7 @@ st_texture_image_unmap(struct st_context *st,
>  {
>     struct pipe_context *pipe = st->pipe;
>     struct pipe_transfer **transfer =
> -      &stImage->transfer[slice + stImage->base.Face];
> +      &stImage->transfer[slice + stImage->base.Face].transfer;
>    DBG("%s\n", __FUNCTION__);
> diff --git a/src/mesa/state_tracker/st_texture.h  
> b/src/mesa/state_tracker/st_texture.h
> index affb568..04b886e 100644
> --- a/src/mesa/state_tracker/st_texture.h
> +++ b/src/mesa/state_tracker/st_texture.h
> @@ -38,6 +38,16 @@
>  struct pipe_resource;
> +struct st_texture_image_transfer {
> +   struct pipe_transfer *transfer;
> +
> +   /* For ETC fallback. */
> +   GLubyte *temp_data; /**< Temporary ETC texture storage. */
> +   unsigned temp_stride; /**< Stride of the ETC texture storage. */
> +   GLubyte *map; /**< Saved map pointer of the uncompressed transfer. */
> +};
> +
> +
>  /**
>   * Subclass of gl_texure_image.
>   */
> @@ -59,7 +69,7 @@ struct st_texture_image
>     /* List of transfers, allocated on demand.
>      * transfer[layer] is a mapping for that layer.
>      */
> -   struct pipe_transfer **transfer;
> +   struct st_texture_image_transfer *transfer;

Nitpick: Might want to call it texture_image_transfer to distinguish it  
 from pipe_transfer where its used.

>     unsigned num_transfers;
>  };


More information about the mesa-dev mailing list