mesa: Add support for array formats of depth and stencil.
authorEric Anholt <eric@anholt.net>
Wed, 18 Sep 2019 21:01:29 +0000 (14:01 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 17 Oct 2019 21:07:29 +0000 (21:07 +0000)
In desktop GL, you can specify things like GL_DEPTH_COMPONENT/GL_BYTE as a
ReadPixels format, and we need to be able to represent that to see if we
have proper MESA_FORMATs for them.  That's exactly what the
mesa_array_format enum is for.

v2: Drop _mesa from static fn.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/main/format_info.py
src/mesa/main/format_utils.c
src/mesa/main/formats.c
src/mesa/main/formats.h
src/mesa/main/glformats.c
src/mesa/main/tests/mesa_formats.cpp

index 432578f4e19106b7b3e3c46a3a41bf2972b35427..d3ec486f155222f5f95a07549e86132e4993a97c 100644 (file)
@@ -176,6 +176,10 @@ static const struct mesa_format_info format_info[MESA_FORMAT_COUNT] =
 def format_channel_bits(fmat, tuple_list):
    return ['.%s = %s' % (field, str(get_channel_bits(fmat, name))) for (field, name) in tuple_list]
 
+bf_map = {
+   "GL_DEPTH_COMPONENT" : "MESA_ARRAY_FORMAT_BASE_FORMAT_DEPTH",
+   "GL_STENCIL_INDEX" : "MESA_ARRAY_FORMAT_BASE_FORMAT_STENCIL",
+}
 
 for fmat in formats:
    print('   {')
@@ -200,6 +204,7 @@ for fmat in formats:
       chan = fmat.array_element()
       norm = chan.norm or chan.type == parser.FLOAT
       print('      .ArrayFormat = MESA_ARRAY_FORMAT({0}),'.format(', '.join([
+         bf_map.get(get_gl_base_format(fmat), "MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS"),
          str(chan.size // 8),
          str(int(chan.sign)),
          str(int(chan.type == parser.FLOAT)),
index 6959bf062a1210b0b0dba66425b73bd31daa6b2f..58a65adc4de5fde303c4f5b24bba72627995be45 100644 (file)
 #include "format_unpack.h"
 
 const mesa_array_format RGBA32_FLOAT =
-   MESA_ARRAY_FORMAT(4, 1, 1, 1, 4, 0, 1, 2, 3);
+   MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS,
+                     4, 1, 1, 1, 4, 0, 1, 2, 3);
 
 const mesa_array_format RGBA8_UBYTE =
-   MESA_ARRAY_FORMAT(1, 0, 0, 1, 4, 0, 1, 2, 3);
+   MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS,
+                     1, 0, 0, 1, 4, 0, 1, 2, 3);
 
 const mesa_array_format RGBA32_UINT =
-   MESA_ARRAY_FORMAT(4, 0, 0, 0, 4, 0, 1, 2, 3);
+   MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS,
+                     4, 0, 0, 0, 4, 0, 1, 2, 3);
 
 const mesa_array_format RGBA32_INT =
-   MESA_ARRAY_FORMAT(4, 1, 0, 0, 4, 0, 1, 2, 3);
+   MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS,
+                     4, 1, 0, 0, 4, 0, 1, 2, 3);
 
 static void
 invert_swizzle(uint8_t dst[4], const uint8_t src[4])
index 1abc83c66ab6f2fe46b2e71cda94fb0b026c3990..b40b275f497ba4e3b8375c635a1110ecd4bd28a6 100644 (file)
@@ -232,6 +232,15 @@ get_base_format_for_array_format(mesa_array_format format)
    uint8_t swizzle[4];
    int num_channels;
 
+   switch (_mesa_array_format_get_base_format(format)) {
+   case MESA_ARRAY_FORMAT_BASE_FORMAT_DEPTH:
+      return GL_DEPTH_COMPONENT;
+   case MESA_ARRAY_FORMAT_BASE_FORMAT_STENCIL:
+      return GL_STENCIL_INDEX;
+   case MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS:
+      break;
+   }
+
    _mesa_array_format_get_swizzle(format, swizzle);
    num_channels = _mesa_array_format_get_num_channels(format);
 
index abfd73313ef3c30f41220f0cfdc6a73466179191..92d0c341df498d0cbecb2b71f5ba97f30a3fda5d 100644 (file)
@@ -109,6 +109,12 @@ enum mesa_array_format_datatype {
    MESA_ARRAY_FORMAT_TYPE_FLOAT = 0xe,
 };
 
+enum mesa_array_format_base_format {
+   MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS = 0x0,
+   MESA_ARRAY_FORMAT_BASE_FORMAT_DEPTH = 0x1,
+   MESA_ARRAY_FORMAT_BASE_FORMAT_STENCIL = 0x2,
+};
+
 /**
  * An enum useful to encode/decode information stored in a mesa_array_format
  */
@@ -124,11 +130,12 @@ enum {
    MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK = 0x03800,
    MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK = 0x1c000,
    MESA_ARRAY_FORMAT_SWIZZLE_W_MASK = 0xe0000,
+   MESA_ARRAY_FORMAT_BASE_FORMAT_MASK = 0x300000,
    MESA_ARRAY_FORMAT_BIT = 0x80000000
 };
 
-#define MESA_ARRAY_FORMAT(SIZE, SIGNED, IS_FLOAT, NORM, NUM_CHANS, \
-      SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) (                \
+#define MESA_ARRAY_FORMAT(BASE_FORMAT, SIZE, SIGNED, IS_FLOAT, NORM, NUM_CHANS, \
+                          SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) ( \
    (((SIZE >> 1)      ) & MESA_ARRAY_FORMAT_TYPE_SIZE_MASK) |      \
    (((SIGNED)    << 2 ) & MESA_ARRAY_FORMAT_TYPE_IS_SIGNED) |      \
    (((IS_FLOAT)  << 3 ) & MESA_ARRAY_FORMAT_TYPE_IS_FLOAT) |       \
@@ -138,6 +145,7 @@ enum {
    (((SWIZZLE_Y) << 11) & MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK) |      \
    (((SWIZZLE_Z) << 14) & MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK) |      \
    (((SWIZZLE_W) << 17) & MESA_ARRAY_FORMAT_SWIZZLE_W_MASK) |      \
+   (((BASE_FORMAT) << 20) & MESA_ARRAY_FORMAT_BASE_FORMAT_MASK) |  \
    MESA_ARRAY_FORMAT_BIT)
 
 /**
@@ -161,6 +169,13 @@ _mesa_array_format_is_normalized(mesa_array_format f)
    return (f & MESA_ARRAY_FORMAT_TYPE_NORMALIZED) !=0;
 }
 
+static inline enum mesa_array_format_base_format
+_mesa_array_format_get_base_format(mesa_array_format f)
+{
+   return (enum mesa_array_format_base_format)
+      ((f & MESA_ARRAY_FORMAT_BASE_FORMAT_MASK) >> 20);
+}
+
 static inline enum mesa_array_format_datatype
 _mesa_array_format_get_datatype(mesa_array_format f)
 {
index f2af50cd855e4f6eb45df312e5eb11391d76b3f3..41becd47d8bbf51ae31da8026448c1640787e5ba 100644 (file)
@@ -3501,6 +3501,12 @@ get_swizzle_from_gl_format(GLenum format, uint8_t *swizzle)
    case GL_INTENSITY:
       set_swizzle(swizzle, 0, 0, 0, 0);
       return true;
+   case GL_DEPTH_COMPONENT:
+      set_swizzle(swizzle, 0, 6, 6, 6);
+      return true;
+   case GL_STENCIL_INDEX:
+      set_swizzle(swizzle, 6, 0, 6, 6);
+      return true;
    default:
       return false;
    }
@@ -3577,10 +3583,24 @@ _mesa_format_from_format_and_type(GLenum format, GLenum type)
     * create the array format
     */
    if (is_array_format) {
-      normalized = !_mesa_is_enum_format_integer(format);
+      enum mesa_array_format_base_format bf;
+      switch (format) {
+      case GL_DEPTH_COMPONENT:
+         bf = MESA_ARRAY_FORMAT_BASE_FORMAT_DEPTH;
+         break;
+      case GL_STENCIL_INDEX:
+         bf = MESA_ARRAY_FORMAT_BASE_FORMAT_STENCIL;
+         break;
+      default:
+         bf = MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS;
+         break;
+      }
+
+      normalized = !(_mesa_is_enum_format_integer(format) ||
+                     format == GL_STENCIL_INDEX);
       num_channels = _mesa_components_in_format(format);
 
-      return MESA_ARRAY_FORMAT(type_size, is_signed, is_float,
+      return MESA_ARRAY_FORMAT(bf, type_size, is_signed, is_float,
                                normalized, num_channels,
                                swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
    }
index 5356cd919a8b5c62c4184fe5380d23d6981048e2..e4f95163c28c548def4cb7aeb8361c23d032a327 100644 (file)
@@ -137,3 +137,25 @@ TEST(MesaFormatsTest, FormatSanity)
 
    }
 }
+
+static mesa_format fffat_wrap(GLenum format, GLenum type)
+{
+   uint32_t f = _mesa_format_from_format_and_type(format, type);
+   if (_mesa_format_is_mesa_array_format(f))
+      f = _mesa_format_from_array_format((mesa_array_format)f);
+   return (mesa_format)f;
+}
+
+TEST(MesaFormatsTest, FormatFromFormatAndType)
+{
+   EXPECT_EQ(fffat_wrap(GL_RGBA, GL_SHORT),
+             MESA_FORMAT_RGBA_SNORM16);
+   EXPECT_EQ(fffat_wrap(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT),
+             MESA_FORMAT_Z_UNORM16);
+   EXPECT_EQ(fffat_wrap(GL_STENCIL_INDEX, GL_UNSIGNED_BYTE),
+             MESA_FORMAT_S_UINT8);
+
+   /* Should return an array format, but not a proper MESA_FORMAT. */
+   EXPECT_TRUE(_mesa_format_is_mesa_array_format(_mesa_format_from_format_and_type(GL_DEPTH_COMPONENT,
+                                                                                   GL_BYTE)));
+}