gdk: Add A16_FLOAT and A32_FLOAT formats

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.
This commit is contained in:
Benjamin Otte 2023-07-21 03:02:33 +02:00
parent 5bd13ccf15
commit 27fbdcbecb
7 changed files with 137 additions and 0 deletions

View 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;

View 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,
}
};

View 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;

View 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 */

View 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;

View 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:

View 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 ();