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

Marek Olšák maraeo at gmail.com
Sun Aug 3 05:40:37 PDT 2014


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
+          * 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.
+          */
+         unsigned z = transfer->box.z;
+         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;
+      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);
+
+      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;
    unsigned num_transfers;
 };
 
-- 
1.9.1



More information about the mesa-dev mailing list