[gtk/gamma-shenanigans: 6/13] Support 16-bit floating point textures
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/gamma-shenanigans: 6/13] Support 16-bit floating point textures
- Date: Thu, 9 Sep 2021 11:10:55 +0000 (UTC)
commit 7949ab329c75e20dab1e60d6a6592dff667312a5
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Sep 6 08:27:42 2021 -0400
Support 16-bit floating point textures
Add R16G16B16_FLOAT, R16G16B16A16_FLOAT and
R16B16B16A16_FLOAT_PREMULTIPLIED formats, which
are using half floats.
The intention is to use these for HDR content.
Not done here: Update memory texture tests
to include floating point textures.
gdk/gdkglcontext.c | 27 ++++++++++
gdk/gdkmemorytexture.c | 118 +++++++++++++++++++++++++++++++++++++++++-
gdk/gdkmemorytexture.h | 10 ++++
testsuite/gdk/memorytexture.c | 5 ++
4 files changed, 158 insertions(+), 2 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 464612e616..45fb907ba0 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -285,6 +285,33 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
gl_type = GL_UNSIGNED_SHORT;
bpp = 8;
}
+ else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
+ {
+ gl_internalformat = GL_RGB16F;
+ gl_format = GL_RGB;
+ gl_type = GL_HALF_FLOAT;
+ bpp = 6;
+ }
+ else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
+ {
+ gl_internalformat = GL_RGBA16F;
+ gl_format = GL_RGBA;
+ gl_type = GL_HALF_FLOAT;
+ bpp = 8;
+ }
+ else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT)
+ {
+ copy = g_malloc (width * height * 8);
+ gdk_memory_convert (copy, width * 8,
+ GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
+ data, stride, data_format,
+ width, height);
+ stride = width * 8;
+ gl_internalformat = GL_RGBA16F;
+ gl_format = GL_RGBA;
+ gl_type = GL_HALF_FLOAT;
+ bpp = 8;
+ }
else /* Fall-back, convert to cairo-surface-format */
{
copy = g_malloc (width * height * 4);
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index e63e2ac209..19dc7c7a11 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "gdkmemorytextureprivate.h"
+#include "gsk/ngl/fp16private.h"
/**
* GdkMemoryTexture:
@@ -63,8 +64,13 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
return 3;
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
+ case GDK_MEMORY_R16G16B16A16_FLOAT:
+ case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
return 8;
+ case GDK_MEMORY_R16G16B16_FLOAT:
+ return 6;
+
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
@@ -330,6 +336,108 @@ SWIZZLE_16TO8(0,1,2,3)
SWIZZLE_16TO8(2,1,0,3)
SWIZZLE_16TO8(1,2,3,0)
+#define SWIZZLE_FP16_OPAQUE(A,R,G,B) \
+static void \
+convert_fp16_swizzle_opaque_ ## A ## R ## G ## B (guchar *dest_data, \
+ gsize dest_stride, \
+ const guchar *src_data, \
+ gsize src_stride, \
+ gsize width, \
+ gsize height) \
+{ \
+ gsize x, y; \
+\
+ for (y = 0; y < height; y++) \
+ { \
+ guint16 *src = (guint16 *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ float c[4]; \
+ half_to_float4 (&src[3 * x], c); \
+ dest_data[4 * x + A] = 255; \
+ dest_data[4 * x + R] = (guchar)(255 * c[0]); \
+ dest_data[4 * x + G] = (guchar)(255 * c[1]); \
+ dest_data[4 * x + B] = (guchar)(255 * c[2]); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_FP16_OPAQUE(3,2,1,0)
+SWIZZLE_FP16_OPAQUE(0,1,2,3)
+SWIZZLE_FP16_OPAQUE(3,0,1,2)
+
+#define SWIZZLE_FP16(A,R,G,B) \
+static void \
+convert_fp16_swizzle_ ## A ## R ## G ## B (guchar *dest_data, \
+ gsize dest_stride, \
+ const guchar *src_data, \
+ gsize src_stride, \
+ gsize width, \
+ gsize height) \
+{ \
+ gsize x, y; \
+\
+ for (y = 0; y < height; y++) \
+ { \
+ guint16 *src = (guint16 *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ float c[4]; \
+ half_to_float4 (&src[3 * x], c); \
+ dest_data[4 * x + A] = (guchar)(255 * c[0]); \
+ dest_data[4 * x + R] = (guchar)(255 * c[1]); \
+ dest_data[4 * x + G] = (guchar)(255 * c[2]); \
+ dest_data[4 * x + B] = (guchar)(255 * c[3]); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_FP16(3,2,1,0)
+SWIZZLE_FP16(0,1,2,3)
+SWIZZLE_FP16(3,0,1,2)
+
+static void
+convert_fp16_premultiply (guchar *dest_data,
+ gsize dest_stride,
+ const guchar *src_data,
+ gsize src_stride,
+ gsize width,
+ gsize height)
+{
+ gsize x, y;
+
+ for (y = 0; y < height; y++)
+ {
+ guint16 *dest = (guint16 *)dest_data;
+ guint16 *src = (guint16 *)src_data;
+
+ for (x = 0; x < width; x++)
+ {
+ float c[4];
+
+ half_to_float4 (&src[x * 4], c);
+
+ if (c[3] != 1.f)
+ {
+ c[1] *= c[3];
+ c[2] *= c[3];
+ c[3] *= c[3];
+ }
+
+ float_to_half4 (c, &dest[x + 4]);
+ }
+
+ dest_data += dest_stride;
+ src_data += src_stride;
+ }
+}
+
typedef void (* ConversionFunc) (guchar *dest_data,
gsize dest_stride,
const guchar *src_data,
@@ -348,7 +456,9 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321,
convert_swizzle_premultiply_3012_0321 },
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
- { convert_16to8_swizzle_2103, convert_16to8_swizzle_1230, convert_16to8_swizzle_0123 }
+ { convert_16to8_swizzle_2103, convert_16to8_swizzle_1230, convert_16to8_swizzle_0123 },
+ { convert_fp16_swizzle_opaque_3210, convert_fp16_swizzle_opaque_0123, convert_fp16_swizzle_opaque_3012 },
+ { convert_fp16_swizzle_3210, convert_fp16_swizzle_0123, convert_fp16_swizzle_3012 }
};
void
@@ -364,5 +474,9 @@ gdk_memory_convert (guchar *dest_data,
g_assert (dest_format < 3);
g_assert (src_format < GDK_MEMORY_N_FORMATS);
- converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
+ if (dest_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED &&
+ src_format == GDK_MEMORY_R16G16B16A16_FLOAT)
+ convert_fp16_premultiply (dest_data, dest_stride, src_data, src_stride, width, height);
+ else
+ converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
}
diff --git a/gdk/gdkmemorytexture.h b/gdk/gdkmemorytexture.h
index 4e463174a6..933bd2f112 100644
--- a/gdk/gdkmemorytexture.h
+++ b/gdk/gdkmemorytexture.h
@@ -45,6 +45,13 @@ G_BEGIN_DECLS
* @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
* blue, alpha. The color values are premultiplied with the alpha value.
* Since 4.6
+ * @GDK_MEMORY_R16G16B16_FLOAT: 3 half-float values; for red, green, blue.
+ * The data is opaque. Since 4.6
+ * @GDK_MEMORY_R16G16B16A16_FLOAT: 4 half-float values; for red, green, blue
+ * and alpha. Since 4.6
+ * @GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: 4 half-float values; for
+ * red, green, blue and alpha. The color values are premultiplied with
+ * the alpha value. Since 4.6
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
* more formats get added, so do not rely on its concrete integer.
*
@@ -73,6 +80,9 @@ typedef enum {
GDK_MEMORY_R8G8B8,
GDK_MEMORY_B8G8R8,
GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
+ GDK_MEMORY_R16G16B16_FLOAT,
+ GDK_MEMORY_R16G16B16A16_FLOAT,
+ GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c
index 00bb489b63..e2b9846c23 100644
--- a/testsuite/gdk/memorytexture.c
+++ b/testsuite/gdk/memorytexture.c
@@ -189,6 +189,11 @@ main (int argc, char *argv[])
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
{
+ if (format == GDK_MEMORY_R16G16B16_FLOAT ||
+ format == GDK_MEMORY_R16G16B16A16_FLOAT ||
+ format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
+ continue;
+
for (color = 0; color < N_COLORS; color++)
{
TestData *test_data = g_new (TestData, 1);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]