st/mesa: convert the ETC1 format to an uncompressed one if unsupported
authorMarek Olšák <marek.olsak@amd.com>
Sat, 2 Aug 2014 19:38:25 +0000 (21:38 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 11 Aug 2014 19:53:57 +0000 (21:53 +0200)
I don't know of any hardware which supports it.
With this, GL_OES_compressed_ETC1_RGB8_texture is supported if RGBA8
is supported.

Reviewed-by: Glenn Kennard <glenn.kennard@gmail.com>
docs/relnotes/10.3.html
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_format.c

index c0828da713dee745bb87c7401ac75f1cb31d2b21..a1f2777129cccfd8632f96543419d5d447e62b62 100644 (file)
@@ -60,6 +60,7 @@ Note: some of the new features are only available with certain drivers.
 <li>GL_ARB_fragment_layer_viewport on nv50, nvc0, llvmpipe, r600</li>
 <li>GL_AMD_vertex_shader_viewport_index on i965/gen7+, r600</li>
 <li>GL_ARB_clear_texture on i965</li>
+<li>GL_OES_compressed_ETC1_RGB8_texture on nv30, nv50, nvc0, r300, r600, radeonsi, softpipe, llvmpipe</li>
 <li>A new software rasterizer driver (kms_swrast_dri.so) that works with
 DRM drivers that don't have a full-fledged GEM (such as qxl or simpledrm)</li>
 </ul>
index 1b065e4f04b021a9ae53b4566e11c4afd9b94215..969a05f5297e855f310224e4f30fc460cc3695c6 100644 (file)
@@ -208,7 +208,8 @@ st_MapTextureImage(struct gl_context *ctx,
    map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1,
                               &transfer);
    if (map) {
-      if (_mesa_is_format_etc2(texImage->TexFormat)) {
+      if (_mesa_is_format_etc2(texImage->TexFormat) ||
+          (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
          /* 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.
@@ -250,7 +251,8 @@ 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)) {
+   if (_mesa_is_format_etc2(texImage->TexFormat) ||
+       (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) {
       /* Decompress the ETC texture to the mapped one. */
       unsigned z = slice + stImage->base.Face;
       struct st_texture_image_transfer *itransfer = &stImage->transfer[z];
@@ -258,10 +260,18 @@ st_UnmapTextureImage(struct gl_context *ctx,
 
       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);
+      if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) {
+         _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride,
+                                    itransfer->temp_data,
+                                    itransfer->temp_stride,
+                                    transfer->box.width, transfer->box.height);
+      }
+      else {
+         _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;
@@ -657,7 +667,8 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
    unsigned bind;
    GLubyte *map;
 
-   assert(!_mesa_is_format_etc2(texImage->TexFormat));
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
 
    if (!st->prefer_blit_based_texture_transfer) {
       goto fallback;
@@ -918,7 +929,8 @@ st_GetTexImage(struct gl_context * ctx,
    ubyte *map = NULL;
    boolean done = FALSE;
 
-   assert(!_mesa_is_format_etc2(texImage->TexFormat));
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
 
    if (!st->prefer_blit_based_texture_transfer &&
        !_mesa_is_format_compressed(texImage->TexFormat)) {
@@ -1356,7 +1368,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    unsigned bind;
    GLint srcY0, srcY1;
 
-   assert(!_mesa_is_format_etc2(texImage->TexFormat));
+   assert(!_mesa_is_format_etc2(texImage->TexFormat) &&
+          texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
 
    if (!strb || !strb->surface || !stImage->pt) {
       debug_printf("%s: null strb or stImage\n", __FUNCTION__);
index c805a094b98d45a2d0697e79ff08bb9577e8d257..ccd19f3e3617deed72c268bbe6a2932f60222901 100644 (file)
@@ -189,6 +189,9 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
    st->has_stencil_export =
       screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
    st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3);
+   st->has_etc1 = screen->is_format_supported(screen, PIPE_FORMAT_ETC1_RGB8,
+                                              PIPE_TEXTURE_2D, 0,
+                                              PIPE_BIND_SAMPLER_VIEW);
    st->prefer_blit_based_texture_transfer = screen->get_param(screen,
                               PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER);
 
index 361a24b1d716a661106ad09514b78f123059b3ef..6d572bd4907c6f5132eb86a984a1aab640a2ea2a 100644 (file)
@@ -86,6 +86,7 @@ struct st_context
    boolean has_stencil_export; /**< can do shader stencil export? */
    boolean has_time_elapsed;
    boolean has_shader_model3;
+   boolean has_etc1;
    boolean prefer_blit_based_texture_transfer;
 
    boolean needs_texcoord_semantic;
index 3974adb49a4cfd8eac624f182039cdaf8e89afd6..60aa8ccec0bcb7057604dec2b9ede61e62710c31 100644 (file)
@@ -513,7 +513,9 @@ void st_init_extensions(struct st_context *st)
         GL_TRUE }, /* at least one format must be supported */
 
       { { o(OES_compressed_ETC1_RGB8_texture) },
-        { PIPE_FORMAT_ETC1_RGB8 } },
+        { PIPE_FORMAT_ETC1_RGB8,
+          PIPE_FORMAT_R8G8B8A8_UNORM },
+        GL_TRUE }, /* at least one format must be supported */
 
       { { o(ARB_stencil_texturing) },
         { PIPE_FORMAT_X24S8_UINT,
index 3d822a5a4e4fa7e7025bf6fc6b5f264c822c7c37..ae71dd786cf06c2514bedf9224337fabae972724 100644 (file)
@@ -323,8 +323,10 @@ st_mesa_format_to_pipe_format(struct st_context *st, mesa_format mesaFormat)
    case MESA_FORMAT_LA_LATC2_SNORM:
       return PIPE_FORMAT_LATC2_SNORM;
 
+   /* The destination RGBA format mustn't be changed, because it's also
+    * a destination format of the unpack/decompression function. */
    case MESA_FORMAT_ETC1_RGB8:
-      return PIPE_FORMAT_ETC1_RGB8;
+      return st->has_etc1 ? PIPE_FORMAT_ETC1_RGB8 : PIPE_FORMAT_R8G8B8A8_UNORM;
 
    /* signed normalized formats */
    case MESA_FORMAT_R_SNORM8:
@@ -801,9 +803,11 @@ test_format_conversion(struct st_context *st)
 
    /* test all Mesa formats */
    for (i = 1; i < MESA_FORMAT_COUNT; i++) {
-      /* ETC2 formats are translated differently, skip them. */
+      /* ETC formats are translated differently, skip them. */
       if (_mesa_is_format_etc2(i))
          continue;
+      if (i == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)
+         continue;
 
       enum pipe_format pf = st_mesa_format_to_pipe_format(st, i);
       if (pf != PIPE_FORMAT_NONE) {
@@ -815,6 +819,11 @@ test_format_conversion(struct st_context *st)
    /* Test all Gallium formats */
    for (i = 1; i < PIPE_FORMAT_COUNT; i++) {
       mesa_format mf = st_pipe_format_to_mesa_format(i);
+
+      /* ETC formats are translated differently, skip them. */
+      if (i == PIPE_FORMAT_ETC1_RGB8 && !st->has_etc1)
+         continue;
+
       if (mf != MESA_FORMAT_NONE) {
          enum pipe_format pf = st_mesa_format_to_pipe_format(st, mf);
          assert(pf == i);