gdk: Add A16_FLOAT and A32_FLOAT formats
authorBenjamin Otte <otte@redhat.com>
Fri, 21 Jul 2023 01:02:33 +0000 (03:02 +0200)
committerBenjamin Otte <otte@redhat.com>
Fri, 21 Jul 2023 23:33:44 +0000 (01:33 +0200)
We need them for mask-only textures.

For tiffs, we convert the formats to RGBA (the idea that tiff can save
everything needs to be buried I guess) as tiffs can't do alpha-only.

gdk/gdkenums.h
gdk/gdkmemoryformat.c
gdk/loaders/gdkpng.c
gdk/loaders/gdktiff.c
gsk/gskrendernodeparser.c
gsk/vulkan/gskvulkanimage.c
testsuite/gdk/memorytexture.c

index f2f7251b663ac69026f3b585b3d85a6f9bc717df..c03cf9f7c7d795584d3adb66f17067986bf03a6c 100644 (file)
@@ -364,6 +364,8 @@ typedef enum {
   GDK_MEMORY_G16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
   GDK_MEMORY_A8 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
   GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
+  GDK_MEMORY_A16_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
+  GDK_MEMORY_A32_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
 
   GDK_MEMORY_N_FORMATS
 } GdkMemoryFormat;
index c4cb2b7d227cd74003c049bc948c96133a7c66c6..9c85ae2575e69f997bc9d1caf7cbd8fc3404ab6c 100644 (file)
@@ -156,6 +156,37 @@ r16g16b16a16_float_from_float (guchar      *dest,
   float_to_half (src, (guint16 *) dest, 4 * n);
 }
 
+static void
+a16_float_to_float (float        *dest,
+                    const guchar *src_data,
+                    gsize         n)
+{
+  const guint16 *src = (const guint16 *) src_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      half_to_float (src, dest, 1);
+      dest[1] = dest[0];
+      dest[2] = dest[0];
+      dest[3] = dest[0];
+      src++;
+      dest += 4;
+    }
+}
+
+static void
+a16_float_from_float (guchar      *dest_data,
+                      const float *src,
+                      gsize        n)
+{
+  guint16 *dest = (guint16 *) dest_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      float_to_half (&src[3], dest, 1);
+      dest ++;
+      src += 4;
+    }
+}
+
 static void
 r32g32b32_float_to_float (float        *dest,
                           const guchar *src_data,
@@ -205,6 +236,37 @@ r32g32b32a32_float_from_float (guchar      *dest,
   memcpy (dest, src, sizeof (float) * n * 4);
 }
 
+static void
+a32_float_to_float (float        *dest,
+                    const guchar *src_data,
+                    gsize         n)
+{
+  const float *src = (const float *) src_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      dest[0] = src[0];
+      dest[1] = src[0];
+      dest[2] = src[0];
+      dest[3] = src[0];
+      src++;
+      dest += 4;
+    }
+}
+
+static void
+a32_float_from_float (guchar      *dest_data,
+                      const float *src,
+                      gsize        n)
+{
+  float *dest = (float *) dest_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      dest[0] = src[3];
+      dest ++;
+      src += 4;
+    }
+}
+
 #define PREMULTIPLY_FUNC(name, R1, G1, B1, A1, R2, G2, B2, A2) \
 static void \
 name (guchar *dest, \
@@ -544,6 +606,26 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
     { GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_ONE, GL_ONE, GL_ONE, GL_RED } },
     a16_to_float,
     a16_from_float,
+  },
+  [GDK_MEMORY_A16_FLOAT] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    2,
+    G_ALIGNOF (guint16),
+    GDK_MEMORY_FLOAT16,
+    { 0, 0, 3, 0 },
+    { GL_R16F, GL_RED, GL_HALF_FLOAT, { GL_RED, GL_RED, GL_RED, GL_RED } },
+    a16_float_to_float,
+    a16_float_from_float,
+  },
+  [GDK_MEMORY_A32_FLOAT] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    4,
+    G_ALIGNOF (float),
+    GDK_MEMORY_FLOAT32,
+    { 0, 0, 3, 0 },
+    { GL_R32F, GL_RED, GL_FLOAT, { GL_RED, GL_RED, GL_RED, GL_RED } },
+    a32_float_to_float,
+    a32_float_from_float,
   }
 };
 
index 2f6d55d1f9c10f182a059746e225eb3b98499758..ebaa103b674ca8c7eb30595283dfa379f50bda2b 100644 (file)
@@ -387,6 +387,8 @@ gdk_save_png (GdkTexture *texture)
     case GDK_MEMORY_G16A16_PREMULTIPLIED:
     case GDK_MEMORY_G16A16:
     case GDK_MEMORY_A16:
+    case GDK_MEMORY_A16_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       format = GDK_MEMORY_G16A16;
       png_format = PNG_COLOR_TYPE_GRAY_ALPHA;
       depth = 16;
index 674211898a15ca86057008900a7fbaaa3587b76f..59d33f11e753fd132d91c7da86f3ff2c391b28c5 100644 (file)
@@ -259,6 +259,8 @@ static const FormatData format_data[] = {
   [GDK_MEMORY_G16]                              = { GDK_MEMORY_G16,                              16, 1, SAMPLEFORMAT_UINT,   0,                      PHOTOMETRIC_MINISBLACK },
   [GDK_MEMORY_A8]                               = { GDK_MEMORY_G8A8,                              8, 2, SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_MINISBLACK },
   [GDK_MEMORY_A16]                              = { GDK_MEMORY_G16A16,                           16, 2, SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_MINISBLACK },
+  [GDK_MEMORY_A16_FLOAT]                        = { GDK_MEMORY_R16G16B16A16_FLOAT,               16, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
+  [GDK_MEMORY_A32_FLOAT]                        = { GDK_MEMORY_R32G32B32A32_FLOAT,               32, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
 };
 
 /* if this fails, somebody forgot to add formats above */
index 923cddf3db7520572dc3fb3cc70f585edab8ae79..7a1b7a9bb147d4e0cd49e4414f571fd64174a65f 100644 (file)
@@ -2931,9 +2931,11 @@ append_texture_param (Printer    *p,
     case GDK_MEMORY_R16G16B16_FLOAT:
     case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
     case GDK_MEMORY_R16G16B16A16_FLOAT:
+    case GDK_MEMORY_A16_FLOAT:
     case GDK_MEMORY_R32G32B32_FLOAT:
     case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
     case GDK_MEMORY_R32G32B32A32_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       bytes = gdk_texture_save_to_tiff_bytes (texture);
       g_string_append (p->str, "url(\"data:image/tiff;base64,");
       break;
index 459551b214d686773fb282263df429bac1950dda..1b92caec678bbdf9c33efd994a63c0af0b29dfd2 100644 (file)
@@ -289,6 +289,24 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
         return info;
       }
 
+    case GDK_MEMORY_A16_FLOAT:
+      {
+        static const GskMemoryFormatInfo info[] = {
+          { VK_FORMAT_R16_SFLOAT, SWIZZLE (R, R, R, R), 0 },
+          { VK_FORMAT_UNDEFINED }
+        };
+        return info;
+      }
+
+    case GDK_MEMORY_A32_FLOAT:
+      {
+        static const GskMemoryFormatInfo info[] = {
+          { VK_FORMAT_R32_SFLOAT, SWIZZLE (R, R, R, R), 0 },
+          { VK_FORMAT_UNDEFINED }
+        };
+        return info;
+      }
+
     case GDK_MEMORY_N_FORMATS:
     default:
       g_assert_not_reached ();
@@ -355,6 +373,10 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
       return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
     case GDK_MEMORY_A16:
       return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
+    case GDK_MEMORY_A16_FLOAT:
+      return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
+    case GDK_MEMORY_A32_FLOAT:
+      return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
 
     case GDK_MEMORY_N_FORMATS:
     default:
index 00e9a36c69865c0d814b26d0a13b455fa10a3a55..c963be8c5b6cd3d2ea3092cd7d55182dda31d72c 100644 (file)
@@ -92,6 +92,7 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
     case GDK_MEMORY_G8A8:
     case GDK_MEMORY_G16:
     case GDK_MEMORY_A16:
+    case GDK_MEMORY_A16_FLOAT:
       return 2;
 
     case GDK_MEMORY_R8G8B8:
@@ -107,6 +108,7 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
     case GDK_MEMORY_A8B8G8R8:
     case GDK_MEMORY_G16A16_PREMULTIPLIED:
     case GDK_MEMORY_G16A16:
+    case GDK_MEMORY_A32_FLOAT:
       return 4;
 
     case GDK_MEMORY_R16G16B16:
@@ -165,11 +167,13 @@ gdk_memory_format_get_channel_type (GdkMemoryFormat format)
     case GDK_MEMORY_R16G16B16_FLOAT:
     case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
     case GDK_MEMORY_R16G16B16A16_FLOAT:
+    case GDK_MEMORY_A16_FLOAT:
       return CHANNEL_FLOAT_16;
 
     case GDK_MEMORY_R32G32B32_FLOAT:
     case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
     case GDK_MEMORY_R32G32B32A32_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       return CHANNEL_FLOAT_32;
 
     case GDK_MEMORY_N_FORMATS:
@@ -215,6 +219,8 @@ gdk_memory_format_n_colors (GdkMemoryFormat format)
 
     case GDK_MEMORY_A8:
     case GDK_MEMORY_A16:
+    case GDK_MEMORY_A16_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       return 0;
 
     case GDK_MEMORY_N_FORMATS:
@@ -257,6 +263,8 @@ gdk_memory_format_has_alpha (GdkMemoryFormat format)
     case GDK_MEMORY_G16A16:
     case GDK_MEMORY_A8:
     case GDK_MEMORY_A16:
+    case GDK_MEMORY_A16_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       return TRUE;
 
     case GDK_MEMORY_N_FORMATS:
@@ -279,6 +287,8 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
     case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
     case GDK_MEMORY_G8A8_PREMULTIPLIED:
     case GDK_MEMORY_G16A16_PREMULTIPLIED:
+    case GDK_MEMORY_A16_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       return TRUE;
 
     case GDK_MEMORY_R8G8B8:
@@ -341,6 +351,8 @@ gdk_memory_format_is_deep (GdkMemoryFormat format)
     case GDK_MEMORY_G16:
     case GDK_MEMORY_G16A16:
     case GDK_MEMORY_A16:
+    case GDK_MEMORY_A16_FLOAT:
+    case GDK_MEMORY_A32_FLOAT:
       return TRUE;
 
     case GDK_MEMORY_N_FORMATS:
@@ -395,6 +407,7 @@ gdk_memory_format_pixel_equal (GdkMemoryFormat  format,
     case GDK_MEMORY_R16G16B16_FLOAT:
     case GDK_MEMORY_R16G16B16A16_FLOAT:
     case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
+    case GDK_MEMORY_A16_FLOAT:
       {
         guint i;
         for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++)
@@ -410,6 +423,7 @@ gdk_memory_format_pixel_equal (GdkMemoryFormat  format,
     case GDK_MEMORY_R32G32B32_FLOAT:
     case GDK_MEMORY_R32G32B32A32_FLOAT:
     case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
+    case GDK_MEMORY_A32_FLOAT:
       {
         const float *f1 = (const float *) pixel1;
         const float *f2 = (const float *) pixel2;
@@ -733,6 +747,17 @@ texture_builder_set_pixel (TextureBuilder  *builder,
         memcpy (data, &pixel,  sizeof (guint16));
       }
       break;
+    case GDK_MEMORY_A16_FLOAT:
+      {
+        guint16 pixel = float_to_half (color->alpha);
+        memcpy (data, &pixel, sizeof (guint16));
+      }
+      break;
+    case GDK_MEMORY_A32_FLOAT:
+      {
+        memcpy (data, &color->alpha, sizeof (float));
+      }
+      break;
     case GDK_MEMORY_N_FORMATS:
     default:
       g_assert_not_reached ();