[gtk/gamma-shenanigans: 8/13] Support 32-bit floating point textures
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/gamma-shenanigans: 8/13] Support 32-bit floating point textures
- Date: Thu, 9 Sep 2021 11:10:55 +0000 (UTC)
commit baeb682e872202b5646ab09afba6921aee840060
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Sep 9 06:36:06 2021 -0400
Support 32-bit floating point textures
Add R32G32B32_FLOAT, R32G32B32A32_FLOAT and
R32G32B32A32_FLOAT_PREMULTIPLIED formats which
are using 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 | 28 ++++++++
gdk/gdkgltexture.c | 13 ++++
gdk/gdkmemorytexture.c | 148 ++++++++++++++++++++++++++++++++++++++++--
gdk/gdkmemorytexture.h | 10 +++
testsuite/gdk/memorytexture.c | 5 +-
5 files changed, 197 insertions(+), 7 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 45fb907ba0..19708dd584 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -312,6 +312,34 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
gl_type = GL_HALF_FLOAT;
bpp = 8;
}
+ else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
+ {
+ gl_internalformat = GL_RGB32F;
+ gl_format = GL_RGB;
+ gl_type = GL_FLOAT;
+ bpp = 12;
+ }
+ else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
+ {
+ gl_internalformat = GL_RGBA32F;
+ gl_format = GL_RGBA;
+ gl_type = GL_FLOAT;
+ bpp = 16;
+ }
+ else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT)
+ {
+ stride = width * 16;
+ copy = g_malloc (stride * height);
+ gdk_memory_convert (copy, stride,
+ GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+ data, stride, data_format,
+ width, height);
+ data = copy;
+ gl_internalformat = GL_RGBA32F;
+ gl_format = GL_RGBA;
+ gl_type = GL_FLOAT;
+ bpp = 16;
+ }
else /* Fall-back, convert to cairo-surface-format */
{
copy = g_malloc (width * height * 4);
diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c
index 0a0460aefa..981414f9f0 100644
--- a/gdk/gdkgltexture.c
+++ b/gdk/gdkgltexture.c
@@ -140,6 +140,19 @@ gdk_gl_texture_download_format (GdkTexture *texture,
glReadPixels (0, 0, texture->width, texture->height,
GL_RGBA16, GL_UNSIGNED_SHORT, data);
+ return g_bytes_new_take (data, size);
+ }
+ else if (format == GDK_MEMORY_R32G32B32_FLOAT)
+ {
+ if (format != GL_RGB32F)
+ return NULL;
+
+ size = texture->width * texture->height * 3 * sizeof (float);
+ data = malloc (size);
+
+ glReadPixels (0, 0, texture->width, texture->height,
+ GL_RGBA32F, GL_FLOAT, data);
+
return g_bytes_new_take (data, size);
}
else
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 2e4a3cf472..c04d18e7da 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -71,6 +71,13 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
case GDK_MEMORY_R16G16B16_FLOAT:
return 6;
+ case GDK_MEMORY_R32G32B32_FLOAT:
+ return 12;
+
+ case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
+ case GDK_MEMORY_R32G32B32A32_FLOAT:
+ return 16;
+
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
@@ -170,7 +177,7 @@ gdk_memory_texture_new (int width,
return GDK_TEXTURE (self);
}
-GdkMemoryFormat
+GdkMemoryFormat
gdk_memory_texture_get_format (GdkMemoryTexture *self)
{
return self->format;
@@ -402,7 +409,7 @@ SWIZZLE_FP16(3,2,1,0)
SWIZZLE_FP16(0,1,2,3)
SWIZZLE_FP16(3,0,1,2)
-#define SWIZZLE_PREMULTIPLY_FP16(A,R,G,B) \
+#define SWIZZLE_FP16_PREMULTIPLY(A,R,G,B) \
static void \
convert_fp16_swizzle_premultiply_ ## A ## R ## G ## B (guchar *dest_data, \
gsize dest_stride, \
@@ -435,9 +442,9 @@ convert_fp16_swizzle_premultiply_ ## A ## R ## G ## B (guchar *dest_data,
} \
}
-SWIZZLE_PREMULTIPLY_FP16(3,2,1,0)
-SWIZZLE_PREMULTIPLY_FP16(0,1,2,3)
-SWIZZLE_PREMULTIPLY_FP16(3,0,1,2)
+SWIZZLE_FP16_PREMULTIPLY(3,2,1,0)
+SWIZZLE_FP16_PREMULTIPLY(0,1,2,3)
+SWIZZLE_FP16_PREMULTIPLY(3,0,1,2)
static void
convert_fp16_premultiply (guchar *dest_data,
@@ -472,6 +479,129 @@ convert_fp16_premultiply (guchar *dest_data,
}
}
+#define SWIZZLE_FLOAT_OPAQUE(A,R,G,B) \
+static void \
+convert_float_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++) \
+ { \
+ float *src = (float *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ dest_data[4 * x + A] = 255; \
+ dest_data[4 * x + R] = (guchar)(255 * src[3 * x + 0]); \
+ dest_data[4 * x + G] = (guchar)(255 * src[3 * x + 1]); \
+ dest_data[4 * x + B] = (guchar)(255 * src[3 * x + 2]); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_FLOAT_OPAQUE(3,2,1,0)
+SWIZZLE_FLOAT_OPAQUE(0,1,2,3)
+SWIZZLE_FLOAT_OPAQUE(3,0,1,2)
+
+#define SWIZZLE_FLOAT(A,R,G,B) \
+static void \
+convert_float_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++) \
+ { \
+ float *src = (float *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ dest_data[4 * x + A] = (guchar)(255 * src[3 * x + 0]); \
+ dest_data[4 * x + R] = (guchar)(255 * src[3 * x + 1]); \
+ dest_data[4 * x + G] = (guchar)(255 * src[3 * x + 2]); \
+ dest_data[4 * x + B] = (guchar)(255 * src[3 * x + 3]); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_FLOAT(3,2,1,0)
+SWIZZLE_FLOAT(0,1,2,3)
+SWIZZLE_FLOAT(3,0,1,2)
+
+#define SWIZZLE_FLOAT_PREMULTIPLY(A,R,G,B) \
+static void \
+convert_float_swizzle_premultiply_ ## 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++) \
+ { \
+ float *src = (float *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ float alpha = src[4 * x + 3]; \
+ dest_data[4 * x + A] = (guchar)(255 * alpha); \
+ dest_data[4 * x + R] = (guchar)(255 * src[4 * x + 0] * alpha); \
+ dest_data[4 * x + G] = (guchar)(255 * src[4 * x + 1] * alpha); \
+ dest_data[4 * x + B] = (guchar)(255 * src[4 * x + 2] * alpha); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_FLOAT_PREMULTIPLY(3,2,1,0)
+SWIZZLE_FLOAT_PREMULTIPLY(0,1,2,3)
+SWIZZLE_FLOAT_PREMULTIPLY(3,0,1,2)
+
+static void convert_float_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++)
+ {
+ float *dest = (float *)dest_data;
+ float *src = (float *)src_data;
+ for (x = 0; x < height; x++)
+ {
+ float alpha = src[4 * x + 3];
+ if (alpha != 1.f)
+ {
+ dest[4 * x ] = src[4 * x ] * alpha;
+ dest[4 * x + 1] = src[4 * x + 1] * alpha;
+ dest[4 * x + 2] = src[4 * x + 2] * alpha;
+ dest[4 * x + 3] = alpha;
+ }
+ }
+ dest_data += dest_stride;
+ src_data += src_stride;
+ }
+}
+
typedef void (* ConversionFunc) (guchar *dest_data,
gsize dest_stride,
const guchar *src_data,
@@ -493,7 +623,10 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
{ 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_premultiply_3210, convert_fp16_swizzle_premultiply_0123,
convert_fp16_swizzle_premultiply_3012 },
- { convert_fp16_swizzle_3210, convert_fp16_swizzle_0123, convert_fp16_swizzle_3012 }
+ { convert_fp16_swizzle_3210, convert_fp16_swizzle_0123, convert_fp16_swizzle_3012 },
+ { convert_float_swizzle_opaque_3210, convert_float_swizzle_opaque_0123, convert_float_swizzle_opaque_3012
},
+ { convert_float_swizzle_premultiply_3210, convert_float_swizzle_premultiply_0123,
convert_float_swizzle_premultiply_3012 },
+ { convert_float_swizzle_3210, convert_float_swizzle_0123, convert_float_swizzle_3012 }
};
void
@@ -512,6 +645,9 @@ gdk_memory_convert (guchar *dest_data,
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 if (src_format == GDK_MEMORY_R32G32B32A32_FLOAT &&
+ dest_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
+ convert_float_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 933bd2f112..fc1bb57f9f 100644
--- a/gdk/gdkmemorytexture.h
+++ b/gdk/gdkmemorytexture.h
@@ -52,6 +52,13 @@ G_BEGIN_DECLS
* @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_B32G32R32_FLOAT: 3 float values; for blue, green, red.
+ * The data is opaque. Since 4.6
+ * @GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: 4 float values; for
+ * red, green, blue and alpha. The color values are premultiplied with
+ * the alpha value. Since 4.6
+ * @GDK_MEMORY_R32G32B32A32_FLOAT: 4 float values; for red, green, blue and
+ * alpha. 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.
*
@@ -83,6 +90,9 @@ typedef enum {
GDK_MEMORY_R16G16B16_FLOAT,
GDK_MEMORY_R16G16B16A16_FLOAT,
GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
+ GDK_MEMORY_R32G32B32_FLOAT,
+ GDK_MEMORY_R32G32B32A32_FLOAT,
+ GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c
index e2b9846c23..f7153bcdad 100644
--- a/testsuite/gdk/memorytexture.c
+++ b/testsuite/gdk/memorytexture.c
@@ -191,7 +191,10 @@ main (int argc, char *argv[])
{
if (format == GDK_MEMORY_R16G16B16_FLOAT ||
format == GDK_MEMORY_R16G16B16A16_FLOAT ||
- format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
+ format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED ||
+ format == GDK_MEMORY_R32G32B32_FLOAT ||
+ format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED ||
+ format == GDK_MEMORY_R32G32B32A32_FLOAT)
continue;
for (color = 0; color < N_COLORS; color++)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]