[Mesa-dev] [PATCH 3/3] intel: Enable GL_OES_compressed_ETC1_RGB8_texture

Chad Versace chad.versace at linux.intel.com
Tue Jul 10 16:55:08 PDT 2012


Enable it for all hardware.

No current hardware supports ETC1, so this patch implements it by
translating the ETC1 data to RGBX data during the call to
glCompressedTexImage2D(). For details, see the doxygen for
intel_mipmap_tree::wraps_etc1.

Passes the Piglit test spec/OES_compressed_ETC1_RGB8_texture/miptree (test
is pending review) and the ETC1 test in the GLES2 conformance suite.

Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
Signed-off-by: Chad Versace <chad.versace at linux.intel.com>
---
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  5 ++
 src/mesa/drivers/dri/intel/intel_extensions.c    |  1 +
 src/mesa/drivers/dri/intel/intel_mipmap_tree.c   | 70 +++++++++++++++++++++++-
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h   | 15 +++++
 4 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 26e65af..794aadb 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -551,6 +551,11 @@ brw_init_surface_formats(struct brw_context *brw)
    ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT] = true;
    ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8] = true;
    ctx->TextureFormatSupported[MESA_FORMAT_Z16] = true;
+
+   /* On hardware that lacks support for ETC1, we map ETC1 to RGBX
+    * during glCompressedTexImage2D(). See intel_mipmap_tree::wraps_etc1.
+    */
+   ctx->TextureFormatSupported[MESA_FORMAT_ETC1_RGB8] = true;
 }
 
 bool
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
index 953b983..844125d 100755
--- a/src/mesa/drivers/dri/intel/intel_extensions.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -91,6 +91,7 @@ intelInitExtensions(struct gl_context *ctx)
    ctx->Extensions.OES_EGL_image = true;
 #endif
    ctx->Extensions.OES_draw_texture = true;
+   ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true;
 
    if (intel->gen >= 6)
       ctx->Const.GLSLVersion = 130;
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 7018c37..74c9924 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -38,6 +38,7 @@
 #include "main/enums.h"
 #include "main/formats.h"
 #include "main/image.h"
+#include "main/texcompress_etc.h"
 #include "main/teximage.h"
 
 #define FILE_DEBUG_FLAG DEBUG_MIPTREE
@@ -180,7 +181,15 @@ intel_miptree_create(struct intel_context *intel,
 {
    struct intel_mipmap_tree *mt;
    uint32_t tiling = I915_TILING_NONE;
-   GLenum base_format = _mesa_get_format_base_format(format);
+   GLenum base_format;
+   bool wraps_etc1 = false;
+
+   if (format == MESA_FORMAT_ETC1_RGB8) {
+      format = MESA_FORMAT_RGBX8888_REV;
+      wraps_etc1 = true;
+   }
+
+   base_format = _mesa_get_format_base_format(format);
 
    if (intel->use_texture_tiling && !_mesa_is_format_compressed(format)) {
       if (intel->gen >= 4 &&
@@ -227,6 +236,7 @@ intel_miptree_create(struct intel_context *intel,
       return NULL;
    }
 
+   mt->wraps_etc1 = wraps_etc1;
    mt->region = intel_region_alloc(intel->intelScreen,
 				   tiling,
 				   mt->cpp,
@@ -978,6 +988,60 @@ intel_miptree_unmap_s8(struct intel_context *intel,
    free(map->buffer);
 }
 
+static void
+intel_miptree_map_etc1(struct intel_context *intel,
+                       struct intel_mipmap_tree *mt,
+                       struct intel_miptree_map *map,
+                       unsigned int level,
+                       unsigned int slice)
+{
+   /* For justification of these invariants,
+    * see intel_mipmap_tree:wraps_etc1.
+    */
+   assert(mt->wraps_etc1);
+   assert(mt->format == MESA_FORMAT_RGBX8888_REV);
+
+   /* From the GL_OES_compressed_ETC1_RGB8_texture spec:
+    *   INVALID_OPERATION is generated by CompressedTexSubImage2D,
+    *   TexSubImage2D, or CopyTexSubImage2D if the texture image <level>
+    *   bound to <target> has internal format ETC1_RGB8_OES.
+    *
+    * This implies that intel_miptree_map_etc1() can only be called from
+    * glCompressedTexImage2D, and hence the assertions below hold.
+    */
+   assert(map->mode & GL_MAP_WRITE_BIT);
+   assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT);
+   assert(map->x == 0);
+   assert(map->y == 0);
+
+   /* Each ETC1 block contains 4x4 pixels in 8 bytes. */
+   map->stride = 2 * map->w;
+   map->buffer = map->ptr = malloc(map->stride * map->h);
+}
+
+static void
+intel_miptree_unmap_etc1(struct intel_context *intel,
+                         struct intel_mipmap_tree *mt,
+                         struct intel_miptree_map *map,
+                         unsigned int level,
+                         unsigned int slice)
+{
+   uint32_t image_x;
+   uint32_t image_y;
+   intel_miptree_get_image_offset(mt, level, 0, slice, &image_x, &image_y);
+
+   uint8_t *xbgr = intel_region_map(intel, mt->region, map->mode)
+                 + image_y * mt->region->pitch * mt->region->cpp
+                 + image_x * mt->region->cpp;
+
+   _mesa_etc1_unpack_rgba8888(xbgr, mt->region->pitch * mt->region->cpp,
+                              map->ptr, map->stride,
+                              map->w, map->h);
+
+   intel_region_unmap(intel, mt->region);
+   free(map->buffer);
+}
+
 /**
  * Mapping function for packed depth/stencil miptrees backed by real separate
  * miptrees for depth and stencil.
@@ -1154,6 +1218,8 @@ intel_miptree_map(struct intel_context *intel,
 
    if (mt->format == MESA_FORMAT_S8) {
       intel_miptree_map_s8(intel, mt, map, level, slice);
+   } else if (mt->wraps_etc1) {
+      intel_miptree_map_etc1(intel, mt, map, level, slice);
    } else if (mt->stencil_mt) {
       intel_miptree_map_depthstencil(intel, mt, map, level, slice);
    } else if (intel->has_llc &&
@@ -1190,6 +1256,8 @@ intel_miptree_unmap(struct intel_context *intel,
 
    if (mt->format == MESA_FORMAT_S8) {
       intel_miptree_unmap_s8(intel, mt, map, level, slice);
+   } else if (mt->wraps_etc1) {
+      intel_miptree_unmap_etc1(intel, mt, map, level, slice);
    } else if (mt->stencil_mt) {
       intel_miptree_unmap_depthstencil(intel, mt, map, level, slice);
    } else if (map->bo) {
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 5c57e02..1b23947 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -154,6 +154,9 @@ struct intel_mipmap_tree
     * MESA_FORMAT_Z32_FLOAT_X24S8, then mt->format will be
     * MESA_FORMAT_Z32_FLOAT, otherwise for MESA_FORMAT_S8_Z24 objects it will be
     * MESA_FORMAT_X8_Z24.
+    *
+    * For ETC1 textures, this is MESA_FORMAT_RGBX8888_REV if the hardware
+    * lacks support for ETC1. See @ref wraps_etc1.
     */
    gl_format format;
 
@@ -242,6 +245,18 @@ struct intel_mipmap_tree
     */
    struct intel_mipmap_tree *stencil_mt;
 
+   /**
+    * \brief The miptree contains RGBX data that was originally ETC1 data.
+    *
+    * On hardware that lacks support for ETC1 textures, we do the
+    * following on calls to glCompressedTexImage2D(GL_ETC1_RGB8_OES):
+    *   1. Create a miptree whose format is MESA_FORMAT_RGBX8888_REV with
+    *      the wraps_etc1 flag set.
+    *   2. Translate the ETC1 data into RGBX.
+    *   3. Store the RGBX data into the miptree and discard the ETC1 data.
+    */
+   bool wraps_etc1;
+
    /* These are also refcounted:
     */
    GLuint refcount;
-- 
1.7.11.1



More information about the mesa-dev mailing list