From 751ccf460d26c60b5c2fc577c1aa4155e836e696 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 8 Sep 2021 09:38:34 -0400 Subject: [PATCH] Allow conversion to hdr formats Add conversion functions that produce GDK_MEMORY_R32G32B32A32_PREMULTIPLIED data, since we want to allow downloading textures in that format. We make use of the new chaining abilities here to cut down on the number of conversion functions. --- gdk/gdkmemorytexture.c | 168 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c index b794ccb2c3..e45be733a7 100644 --- a/gdk/gdkmemorytexture.c +++ b/gdk/gdkmemorytexture.c @@ -591,11 +591,177 @@ static ConversionFunc converters_to_rgba[GDK_MEMORY_N_FORMATS] = convert_float_swizzle_3012 }; +static void +convert_rgba_to_hdr (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + gsize x, y; + + for (y = 0; y < height; y++) + { + guint16 *src = (guint16 *)src_data; + float *dest = (float *)dest_data; + for (x = 0; x < width; x++) + { + dest[4 * (y * width + x) + 0] = src[3 * (y * width + x) + 0] / 255.f; + dest[4 * (y * width + x) + 1] = src[3 * (y * width + x) + 1] / 255.f; + dest[4 * (y * width + x) + 2] = src[3 * (y * width + x) + 2] / 255.f; + dest[4 * (y * width + x) + 3] = src[3 * (y * width + x) + 3] / 255.f; + } + dest_data += dest_stride; + src_data += src_stride; + } +} + +static void +convert_8bit_to_hdr (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + guchar *data; + + /* TODO: this could perhaps be done in-place */ + data = g_malloc (width * height * 4); + + gdk_memory_convert (data, 4 * width, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, + src_data, src_stride, src_format, + width, height); + convert_rgba_to_hdr (dest_data, dest_stride, dest_format, + data, 4 * width, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, + width, height); + + g_free (data); +} + +static void +convert_16bit_to_hdr (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + gsize x, y; + + for (y = 0; y < height; y++) + { + guint16 *src = (guint16 *)src_data; + float *dest = (float *)dest_data; + for (x = 0; x < width; x++) + { + dest[4 * (y * width + x) + 0] = src[3 * (y * width + x) + 0] / 65535.f; + dest[4 * (y * width + x) + 1] = src[3 * (y * width + x) + 1] / 65535.f; + dest[4 * (y * width + x) + 2] = src[3 * (y * width + x) + 2] / 65535.f; + dest[4 * (y * width + x) + 3] = src[3 * (y * width + x) + 3] / 65535.f; + } + dest_data += dest_stride; + src_data += src_stride; + } +} + +static void +convert_fp16_to_hdr (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + gsize x, y; + int src_bpp; + + if (src_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED) + src_bpp = 4; + else + src_bpp = 3; + + for (y = 0; y < height; y++) + { + guint16 *src = (guint16 *)src_data; + float *dest = (float *)dest_data; + for (x = 0; x < width; x++) + { + guint16 h[4]; + + h[0] = src[src_bpp * (y * width + x)]; + h[1] = src[src_bpp * (y * width + x) + 1]; + h[2] = src[src_bpp * (y * width + x) + 2]; + if (src_bpp == 4) + h[3] = src[src_bpp * (y * width + x) + 3]; + else + h[3] = FP16_ONE; + half_to_float4 (h, &dest[4 * (y * width + x)]); + } + dest_data += dest_stride; + src_data += src_stride; + } +} + +static void +convert_float_to_hdr (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + gsize x, y; + + for (y = 0; y < height; y++) + { + float *src = (float *)src_data; + float *dest = (float *)dest_data; + for (x = 0; x < width; x++) + { + dest[4 * (y * width + x) + 0] = src[3 * (y * width + x) + 0]; + dest[4 * (y * width + x) + 1] = src[3 * (y * width + x) + 1]; + dest[4 * (y * width + x) + 2] = src[3 * (y * width + x) + 2]; + dest[4 * (y * width + x) + 3] = 1.0; + } + dest_data += dest_stride; + src_data += src_stride; + } +} + +static ConversionFunc converters_to_hdr[GDK_MEMORY_N_FORMATS] = +{ + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_rgba_to_hdr, + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_8bit_to_hdr, + convert_16bit_to_hdr, + convert_fp16_to_hdr, + convert_fp16_to_hdr, + convert_float_to_hdr, + convert_memcpy +}; static ConversionFunc* converters[GDK_MEMORY_N_FORMATS] = { converters_to_bgra, converters_to_argb, converters_to_rgba, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL + converters_to_hdr }; void