summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-10-07 02:03:48 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-10-07 02:03:48 +0000
commit8d9c3920bbb7220c8d6252cfb9ad78136bad913e (patch)
tree6f1d807bd697efb6b9b8976696feeeeb35bd298d
parentdb86b3ea2e8c3098a2acdf8bb6cc3cc11578b971 (diff)
parent6f1742970d788880b4e16073289d8c3e636de45e (diff)
downloadgtk+-8d9c3920bbb7220c8d6252cfb9ad78136bad913e.tar.gz
Merge branch 'wip/matthiasc/gsk-hdr' into 'master'
texture: Add hdr api See merge request GNOME/gtk!4036
-rw-r--r--gdk/broadway/gdkcairocontext-broadway.c2
-rw-r--r--gdk/broadway/gdkdrawcontext-broadway.c2
-rw-r--r--gdk/gdk.c2
-rw-r--r--gdk/gdkcairo.c76
-rw-r--r--gdk/gdkdebug.h2
-rw-r--r--gdk/gdkdisplay.c26
-rw-r--r--gdk/gdkdisplayprivate.h3
-rw-r--r--gdk/gdkdrawcontext.c32
-rw-r--r--gdk/gdkdrawcontextprivate.h4
-rw-r--r--gdk/gdkglcontext.c96
-rw-r--r--gdk/gdkgltexture.c134
-rw-r--r--gdk/gdkmemoryformat.c467
-rw-r--r--gdk/gdkmemoryformatprivate.h48
-rw-r--r--gdk/gdkmemorytexture.c530
-rw-r--r--gdk/gdkmemorytextureprivate.h36
-rw-r--r--gdk/gdksurface.c14
-rw-r--r--gdk/gdktexture.c7
-rw-r--r--gdk/gdktextureprivate.h4
-rw-r--r--gdk/gdkvulkancontext.c2
-rw-r--r--gdk/loaders/gdkpng.c3
-rw-r--r--gdk/loaders/gdktiff.c3
-rw-r--r--gdk/macos/gdkmacoscairocontext.c2
-rw-r--r--gdk/macos/gdkmacosglcontext.c4
-rw-r--r--gdk/meson.build1
-rw-r--r--gdk/wayland/gdkcairocontext-wayland.c2
-rw-r--r--gdk/wayland/gdkglcontext-wayland.c4
-rw-r--r--gdk/win32/gdkcairocontext-win32.c2
-rw-r--r--gdk/win32/gdkglcontext-win32-egl.c4
-rw-r--r--gdk/win32/gdkglcontext-win32-wgl.c4
-rw-r--r--gdk/win32/gdkvulkancontext-win32.c4
-rw-r--r--gdk/x11/gdkcairocontext-x11.c2
-rw-r--r--gdk/x11/gdkglcontext-egl.c4
-rw-r--r--gsk/gskrendernode.c5
-rw-r--r--gsk/gskrendernodeimpl.c32
-rw-r--r--gsk/gskrendernodeprivate.h3
-rw-r--r--gsk/ngl/gsknglcommandqueue.c12
-rw-r--r--gsk/ngl/gsknglcommandqueueprivate.h2
-rw-r--r--gsk/ngl/gskngldriver.c20
-rw-r--r--gsk/ngl/gskngldriverprivate.h3
-rw-r--r--gsk/ngl/gsknglglyphlibrary.c4
-rw-r--r--gsk/ngl/gskngliconlibrary.c4
-rw-r--r--gsk/ngl/gsknglrenderer.c11
-rw-r--r--gsk/ngl/gsknglrenderjob.c38
-rw-r--r--gsk/ngl/gskngltexture.c2
-rw-r--r--gsk/ngl/gskngltexturelibrary.c2
-rw-r--r--gsk/ngl/gskngltextureprivate.h2
-rw-r--r--testsuite/gdk/texture.c26
47 files changed, 849 insertions, 843 deletions
diff --git a/gdk/broadway/gdkcairocontext-broadway.c b/gdk/broadway/gdkcairocontext-broadway.c
index 46fdbaf637..c2924bdf29 100644
--- a/gdk/broadway/gdkcairocontext-broadway.c
+++ b/gdk/broadway/gdkcairocontext-broadway.c
@@ -34,7 +34,7 @@ gdk_broadway_cairo_context_dispose (GObject *object)
static void
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
diff --git a/gdk/broadway/gdkdrawcontext-broadway.c b/gdk/broadway/gdkdrawcontext-broadway.c
index 660976bff5..da65aab78a 100644
--- a/gdk/broadway/gdkdrawcontext-broadway.c
+++ b/gdk/broadway/gdkdrawcontext-broadway.c
@@ -34,7 +34,7 @@ gdk_broadway_draw_context_dispose (GObject *object)
static void
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
diff --git a/gdk/gdk.c b/gdk/gdk.c
index b050c5916b..123b0413ef 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -129,7 +129,7 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
- { "hdr", GDK_DEBUG_HDR, "Use HDR rendering if possible", TRUE },
+ { "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible", TRUE },
};
diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c
index ef8f5d2fb5..d69b9bc602 100644
--- a/gdk/gdkcairo.c
+++ b/gdk/gdkcairo.c
@@ -91,11 +91,7 @@ void
gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
const GdkPixbuf *pixbuf)
{
- int width, height;
- guchar *gdk_pixels, *cairo_pixels;
- int gdk_rowstride, cairo_stride;
- int n_channels;
- int j;
+ GdkTexture *texture;
if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
return;
@@ -111,71 +107,11 @@ gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
cairo_surface_flush (surface);
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
- gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- n_channels = gdk_pixbuf_get_n_channels (pixbuf);
- cairo_stride = cairo_image_surface_get_stride (surface);
- cairo_pixels = cairo_image_surface_get_data (surface);
-
- for (j = height; j; j--)
- {
- guchar *p = gdk_pixels;
- guchar *q = cairo_pixels;
-
- if (n_channels == 3)
- {
- guchar *end = p + 3 * width;
-
- while (p < end)
- {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- q[0] = p[2];
- q[1] = p[1];
- q[2] = p[0];
- q[3] = 0xFF;
-#else
- q[0] = 0xFF;
- q[1] = p[0];
- q[2] = p[1];
- q[3] = p[2];
-#endif
- p += 3;
- q += 4;
- }
- }
- else
- {
- guchar *end = p + 4 * width;
- guint t1,t2,t3;
-
-#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
-
- while (p < end)
- {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- MULT(q[0], p[2], p[3], t1);
- MULT(q[1], p[1], p[3], t2);
- MULT(q[2], p[0], p[3], t3);
- q[3] = p[3];
-#else
- q[0] = p[3];
- MULT(q[1], p[0], p[3], t1);
- MULT(q[2], p[1], p[3], t2);
- MULT(q[3], p[2], p[3], t3);
-#endif
-
- p += 4;
- q += 4;
- }
-
-#undef MULT
- }
-
- gdk_pixels += gdk_rowstride;
- cairo_pixels += cairo_stride;
- }
+ texture = gdk_texture_new_for_pixbuf (GDK_PIXBUF (pixbuf));
+ gdk_texture_download (texture,
+ cairo_image_surface_get_data (surface),
+ cairo_image_surface_get_stride (surface));
+ g_object_unref (texture);
cairo_surface_mark_dirty (surface);
}
diff --git a/gdk/gdkdebug.h b/gdk/gdkdebug.h
index 52460a7a82..acd2259440 100644
--- a/gdk/gdkdebug.h
+++ b/gdk/gdkdebug.h
@@ -50,7 +50,7 @@ typedef enum {
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
- GDK_DEBUG_HDR = 1 << 24,
+ GDK_DEBUG_HIGH_DEPTH = 1 << 24,
} GdkDebugFlags;
extern guint _gdk_debug_flags;
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 875cf5c82b..7d36f2e371 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -93,7 +93,7 @@ struct _GdkDisplayPrivate {
#ifdef HAVE_EGL
EGLDisplay egl_display;
EGLConfig egl_config;
- EGLConfig egl_config_hdr;
+ EGLConfig egl_config_high_depth;
#endif
guint rgba : 1;
@@ -1439,11 +1439,11 @@ gdk_display_get_egl_config (GdkDisplay *self)
}
gpointer
-gdk_display_get_egl_config_hdr (GdkDisplay *self)
+gdk_display_get_egl_config_high_depth (GdkDisplay *self)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
- return priv->egl_config_hdr;
+ return priv->egl_config_high_depth;
}
static EGLDisplay
@@ -1721,16 +1721,16 @@ gdk_display_init_egl (GdkDisplay *self,
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
if (self->have_egl_no_config_context)
- priv->egl_config_hdr = gdk_display_create_egl_config (self,
+ priv->egl_config_high_depth = gdk_display_create_egl_config (self,
GDK_EGL_CONFIG_HDR,
error);
- if (priv->egl_config_hdr == NULL)
- priv->egl_config_hdr = priv->egl_config;
+ if (priv->egl_config_high_depth == NULL)
+ priv->egl_config_high_depth = priv->egl_config;
GDK_DISPLAY_NOTE (self, OPENGL, {
char *ext = describe_extensions (priv->egl_display);
- char *sdr_cfg = describe_egl_config (priv->egl_display, priv->egl_config);
- char *hdr_cfg = describe_egl_config (priv->egl_display, priv->egl_config_hdr);
+ char *std_cfg = describe_egl_config (priv->egl_display, priv->egl_config);
+ char *hd_cfg = describe_egl_config (priv->egl_display, priv->egl_config_high_depth);
g_message ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Version: %s\n"
@@ -1738,15 +1738,15 @@ gdk_display_init_egl (GdkDisplay *self,
" - Extensions:\n"
"\t%s\n"
" - Selected fbconfig: %s\n"
- " HDR fbconfig: %s",
+ " high depth: %s",
major, minor,
eglQueryString (priv->egl_display, EGL_VENDOR),
eglQueryString (priv->egl_display, EGL_VERSION),
eglQueryString (priv->egl_display, EGL_CLIENT_APIS),
- ext, sdr_cfg,
- priv->egl_config_hdr == priv->egl_config ? "none" : hdr_cfg);
- g_free (hdr_cfg);
- g_free (sdr_cfg);
+ ext, std_cfg,
+ priv->egl_config_high_depth == priv->egl_config ? "none" : hd_cfg);
+ g_free (hd_cfg);
+ g_free (std_cfg);
g_free (ext);
});
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index 4cb85b2ea4..cb80ad3f88 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -226,7 +226,8 @@ gboolean gdk_display_init_egl (GdkDisplay *display
GError **error);
gpointer gdk_display_get_egl_display (GdkDisplay *display);
gpointer gdk_display_get_egl_config (GdkDisplay *display);
-gpointer gdk_display_get_egl_config_hdr (GdkDisplay *display);
+gpointer gdk_display_get_egl_config_high_depth
+ (GdkDisplay *display);
void gdk_display_set_rgba (GdkDisplay *display,
gboolean rgba);
diff --git a/gdk/gdkdrawcontext.c b/gdk/gdkdrawcontext.c
index b1988c4034..b51e1139dd 100644
--- a/gdk/gdkdrawcontext.c
+++ b/gdk/gdkdrawcontext.c
@@ -315,28 +315,30 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
}
/*
- * @request_hdr: %TRUE to request high dynamic range.
+ * @prefers_high_depth: %TRUE to request a higher bit depth
*
- * If HDR is requested, GDK will see about providing a rendering target
- * that supports high dynamic range. Typically this means a target supporting
- * 16bit floating point pixels, but that is not guaranteed.
+ * If high depth is preferred, GDK will see about providing a rendering target
+ * that supports higher bit depth than 8 bits per channel. Typically this means
+ * a target supporting 16bit floating point pixels, but that is not guaranteed.
*
* This is only a request and if the GDK backend does not support HDR rendering
* or does not consider it worthwhile, it may choose to not honor the request.
- * It may also choose to provide HDR even if it was not requested.
+ * It may also choose to provide high depth even if it was not requested.
* Typically the steps undertaken by a backend are:
- * 1. Check if HDR is supported by this drawing backend.
- * 2. Check if the compositor supports HDR.
- * 3. Check if the compositor prefers SDR. This is usually the case when the attached
- * monitors do not support HDR content or when the system is resource constrained.
+ * 1. Check if high depth is supported by this drawing backend.
+ * 2. Check if the compositor supports high depth.
+ * 3. Check if the compositor prefers regular bit depth. This is usually the case
+ * when the attached monitors do not support high depth content or when the
+ * system is resource constrained.
* In either of those cases, the context will usually choose to not honor the request.
*
- * The rendering code must be able to deal with HDR and SDR content, no matter if HDR
- * was requested. The request is only a hint and GDK is free to choose.
+ * The rendering code must be able to deal with content in any bit depth, no matter
+ * the preference. The prefers_high_depth argument is only a hint and GDK is free
+ * to choose.
*/
void
gdk_draw_context_begin_frame_full (GdkDrawContext *context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
const cairo_region_t *region)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
@@ -362,13 +364,13 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
return;
}
- if (GDK_DISPLAY_DEBUG_CHECK (priv->display, HDR))
- request_hdr = TRUE;
+ if (GDK_DISPLAY_DEBUG_CHECK (priv->display, HIGH_DEPTH))
+ prefers_high_depth = TRUE;
priv->frame_region = cairo_region_copy (region);
priv->surface->paint_context = g_object_ref (context);
- GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, request_hdr, priv->frame_region);
+ GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region);
}
#ifdef HAVE_SYSPROF
diff --git a/gdk/gdkdrawcontextprivate.h b/gdk/gdkdrawcontextprivate.h
index 0171876d9d..4674d25f30 100644
--- a/gdk/gdkdrawcontextprivate.h
+++ b/gdk/gdkdrawcontextprivate.h
@@ -41,7 +41,7 @@ struct _GdkDrawContextClass
GObjectClass parent_class;
void (* begin_frame) (GdkDrawContext *context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *update_area);
void (* end_frame) (GdkDrawContext *context,
cairo_region_t *painted);
@@ -51,7 +51,7 @@ struct _GdkDrawContextClass
void gdk_draw_context_surface_resized (GdkDrawContext *context);
void gdk_draw_context_begin_frame_full (GdkDrawContext *context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
const cairo_region_t *region);
G_END_DECLS
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 11c3f77dd4..5ea41cdeec 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -79,6 +79,7 @@
#include "gdkdebug.h"
#include "gdkdisplayprivate.h"
#include "gdkintl.h"
+#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
@@ -238,80 +239,39 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
guchar *copy = NULL;
- GLint gl_internalformat;
- GLint gl_format;
- GLint gl_type;
+ GLenum gl_internalformat;
+ GLenum gl_format;
+ GLenum gl_type;
gsize bpp;
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
- if (!priv->use_es && data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
+ if (!gdk_memory_format_gl_format (data_format,
+ priv->use_es,
+ &gl_internalformat,
+ &gl_format,
+ &gl_type))
{
- gl_internalformat = GL_RGBA8;
- gl_format = GL_BGRA;
- gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- }
- else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
- {
- gl_internalformat = GL_RGBA8;
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_BYTE;
- }
- else if (priv->use_es && data_format == GDK_MEMORY_B8G8R8)
- {
- gl_internalformat = GL_RGBA8;
- gl_format = GL_BGR;
- gl_type = GL_UNSIGNED_BYTE;
- }
- else if (data_format == GDK_MEMORY_R16G16B16)
- {
- gl_internalformat = GL_RGBA16;
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_SHORT;
- }
- else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
- {
- gl_internalformat = GL_RGBA16;
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_SHORT;
- }
- else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
- {
- gl_internalformat = GL_RGB16F;
- gl_format = GL_RGB;
- gl_type = GL_HALF_FLOAT;
- }
- else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
- {
- gl_internalformat = GL_RGBA16F;
- gl_format = GL_RGBA;
- gl_type = GL_HALF_FLOAT;
- }
- else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
- {
- gl_internalformat = GL_RGB32F;
- gl_format = GL_RGB;
- gl_type = GL_FLOAT;
- }
- else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
- {
- gl_internalformat = GL_RGBA32F;
- gl_format = GL_RGBA;
- gl_type = GL_FLOAT;
- }
- else /* Fall-back, convert to GLES format */
- {
- copy = g_malloc (width * height * 4);
+ copy = g_malloc_n (width * 4, height);
gdk_memory_convert (copy, width * 4,
- GDK_MEMORY_CONVERT_GLES_RGBA,
- data, stride, data_format,
+ GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
+ data, stride,
+ data_format,
width, height);
- data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
- stride = width * 4;
data = copy;
- gl_internalformat = GL_RGBA8;
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_BYTE;
+ data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
+ if (!gdk_memory_format_gl_format (data_format,
+ priv->use_es,
+ &gl_internalformat,
+ &gl_format,
+ &gl_type))
+ {
+ g_assert_not_reached ();
+ }
+ }
+ else
+ {
+ copy = NULL;
}
bpp = gdk_memory_format_bytes_per_pixel (data_format);
@@ -629,7 +589,7 @@ gdk_gl_context_real_make_current (GdkGLContext *context,
static void
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
@@ -642,7 +602,7 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
#ifdef HAVE_EGL
if (priv->egl_context)
- gdk_surface_ensure_egl_surface (surface, request_hdr);
+ gdk_surface_ensure_egl_surface (surface, prefers_high_depth);
#endif
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c
index e2e292964d..e39fcd3fbb 100644
--- a/gdk/gdkgltexture.c
+++ b/gdk/gdkgltexture.c
@@ -21,6 +21,7 @@
#include "gdkgltextureprivate.h"
#include "gdkdisplayprivate.h"
+#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdktextureprivate.h"
@@ -139,82 +140,29 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self,
data);
}
}
+
static void
gdk_gl_texture_do_download_texture (gpointer texture_,
gpointer result_)
{
GdkTexture *texture = texture_;
GdkTexture **result = result_;
- GdkMemoryFormat format;
- GLint internal_format, gl_format, gl_type;
+ guint gl_internalformat, gl_format, gl_type;
guchar *data;
gsize stride;
GBytes *bytes;
- glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
-
- switch (internal_format)
- {
- case GL_RGB8:
- format = GDK_MEMORY_R8G8B8;
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_BYTE;
- break;
-
- case GL_RGBA8:
- format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_BYTE;
- break;
-
- case GL_RGB16:
- format = GDK_MEMORY_R16G16B16;
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_SHORT;
- break;
-
- case GL_RGBA16:
- format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_SHORT;
- break;
-
- case GL_RGB16F:
- format = GDK_MEMORY_R16G16B16_FLOAT;
- gl_format = GL_RGB;
- gl_type = GL_HALF_FLOAT;
- break;
-
- case GL_RGBA16F:
- format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
- gl_format = GL_RGBA;
- gl_type = GL_HALF_FLOAT;
- break;
-
- case GL_RGB32F:
- format = GDK_MEMORY_R32G32B32_FLOAT;
- gl_format = GL_RGB;
- gl_type = GL_FLOAT;
- break;
-
- case GL_RGBA32F:
- format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
- gl_format = GL_RGBA;
- gl_type = GL_FLOAT;
- break;
-
- default:
- g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
- /* fallback to the dumbest possible format
- * so that even age old GLES can do it */
- format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_BYTE;
- break;
- }
+ if (!gdk_memory_format_gl_format (texture->format,
+ gdk_gl_context_get_use_es (gdk_gl_context_get_current ()),
+ &gl_internalformat,
+ &gl_format,
+ &gl_type))
+ {
+ g_assert_not_reached ();
+ }
- stride = gdk_memory_format_bytes_per_pixel (format) * texture->width;
- data = g_malloc (stride * texture->height);
+ stride = gdk_memory_format_bytes_per_pixel (texture->format) * texture->width;
+ data = g_malloc_n (stride, texture->height);
gdk_gl_texture_get_tex_image (texture_,
gl_format,
@@ -224,7 +172,7 @@ gdk_gl_texture_do_download_texture (gpointer texture_,
bytes = g_bytes_new_take (data, stride * texture->height);
*result = gdk_memory_texture_new (texture->width,
texture->height,
- format,
+ texture->format,
bytes,
stride);
@@ -377,6 +325,58 @@ gdk_gl_texture_release (GdkGLTexture *self)
self->id = 0;
}
+static void
+gdk_gl_texture_do_determine_format (gpointer texture_,
+ gpointer unused)
+{
+ GdkTexture *texture = texture_;
+ GLint internal_format;
+
+ glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
+
+ switch (internal_format)
+ {
+ case GL_RGB8:
+ texture->format = GDK_MEMORY_R8G8B8;
+ break;
+
+ case GL_RGBA8:
+ texture->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
+ break;
+
+ case GL_RGB16:
+ texture->format = GDK_MEMORY_R16G16B16;
+ break;
+
+ case GL_RGBA16:
+ texture->format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
+ break;
+
+ case GL_RGB16F:
+ texture->format = GDK_MEMORY_R16G16B16_FLOAT;
+ break;
+
+ case GL_RGBA16F:
+ texture->format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
+ break;
+
+ case GL_RGB32F:
+ texture->format = GDK_MEMORY_R32G32B32_FLOAT;
+ break;
+
+ case GL_RGBA32F:
+ texture->format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
+ break;
+
+ default:
+ g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
+ /* fallback to the dumbest possible format
+ * so that even age old GLES can do it */
+ texture->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
+ break;
+ }
+}
+
/**
* gdk_gl_texture_new:
* @context: a `GdkGLContext`
@@ -420,6 +420,8 @@ gdk_gl_texture_new (GdkGLContext *context,
self->destroy = destroy;
self->data = data;
+ gdk_gl_texture_run (self, gdk_gl_texture_do_determine_format, NULL);
+
return GDK_TEXTURE (self);
}
diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c
new file mode 100644
index 0000000000..5af2bb8516
--- /dev/null
+++ b/gdk/gdkmemoryformat.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright © 2021 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gdkmemoryformatprivate.h"
+
+#include "gsk/ngl/fp16private.h"
+
+#include <epoxy/gl.h>
+
+typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription;
+
+typedef enum {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ GDK_MEMORY_ALPHA_STRAIGHT,
+ GDK_MEMORY_ALPHA_OPAQUE
+} GdkMemoryAlpha;
+
+#define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \
+static void \
+name ## _to_float (float *dest, \
+ const guchar *src_data, \
+ gsize n) \
+{ \
+ for (gsize i = 0; i < n; i++) \
+ { \
+ T *src = (T *) (src_data + i * bpp); \
+ dest[0] = (float) src[R] / scale; \
+ dest[1] = (float) src[G] / scale; \
+ dest[2] = (float) src[B] / scale; \
+ if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \
+ dest += 4; \
+ } \
+} \
+\
+static void \
+name ## _from_float (guchar *dest_data, \
+ const float *src, \
+ gsize n) \
+{ \
+ for (gsize i = 0; i < n; i++) \
+ { \
+ T *dest = (T *) (dest_data + i * bpp); \
+ dest[R] = CLAMP (src[0] * scale + 0.5, 0, scale); \
+ dest[G] = CLAMP (src[1] * scale + 0.5, 0, scale); \
+ dest[B] = CLAMP (src[2] * scale + 0.5, 0, scale); \
+ if (A >= 0) dest[A] = CLAMP (src[3] * scale + 0.5, 0, scale); \
+ src += 4; \
+ } \
+}
+
+TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
+TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
+TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
+TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
+TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
+TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
+TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
+TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
+TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
+TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
+TYPED_FUNCS (r16g16b16a16, guint16, 0, 1, 2, 3, 8, 65535)
+
+static void
+r16g16b16_float_to_float (float *dest,
+ const guchar *src_data,
+ gsize n)
+{
+ guint16 *src = (guint16 *) src_data;
+ for (gsize i = 0; i < n; i++)
+ {
+ half_to_float (src, dest, 3);
+ dest[3] = 1.0;
+ dest += 4;
+ src += 3;
+ }
+}
+
+static void
+r16g16b16_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, dest, 3);
+ dest += 3;
+ src += 4;
+ }
+}
+
+static void
+r16g16b16a16_float_to_float (float *dest,
+ const guchar *src,
+ gsize n)
+{
+ half_to_float ((const guint16 *) src, dest, 4 * n);
+}
+
+static void
+r16g16b16a16_float_from_float (guchar *dest,
+ const float *src,
+ gsize n)
+{
+ float_to_half (src, (guint16 *) dest, 4 * n);
+}
+
+static void
+r32g32b32_float_to_float (float *dest,
+ const guchar *src_data,
+ gsize n)
+{
+ float *src = (float *) src_data;
+ for (gsize i = 0; i < n; i++)
+ {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = 1.0;
+ dest += 4;
+ src += 3;
+ }
+}
+
+static void
+r32g32b32_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[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest += 3;
+ src += 4;
+ }
+}
+
+static void
+r32g32b32a32_float_to_float (float *dest,
+ const guchar *src,
+ gsize n)
+{
+ memcpy (dest, src, sizeof (float) * n * 4);
+}
+
+static void
+r32g32b32a32_float_from_float (guchar *dest,
+ const float *src,
+ gsize n)
+{
+ memcpy (dest, src, sizeof (float) * n * 4);
+}
+
+struct _GdkMemoryFormatDescription
+{
+ GdkMemoryAlpha alpha;
+ gsize bytes_per_pixel;
+ gsize alignment;
+ gboolean prefers_high_depth;
+ gboolean supports_gles;
+ struct {
+ guint internal_format;
+ guint format;
+ guint type;
+ } gl;
+ /* no premultiplication going on here */
+ void (* to_float) (float *, const guchar*, gsize);
+ void (* from_float) (guchar *, const float *, gsize);
+};
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+# define GDK_GL_UNSIGNED_BYTE_FLIPPED GL_UNSIGNED_INT_8_8_8_8
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+# define GDK_GL_UNSIGNED_BYTE_FLIPPED GL_UNSIGNED_INT_8_8_8_8_REV
+#else
+# error "Define the right GL flags here"
+#endif
+
+static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
+ [GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
+ b8g8r8a8_premultiplied_to_float,
+ b8g8r8a8_premultiplied_from_float,
+ },
+ [GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
+ a8r8g8b8_premultiplied_to_float,
+ a8r8g8b8_premultiplied_from_float,
+ },
+ [GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ TRUE,
+ { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
+ r8g8b8a8_premultiplied_to_float,
+ r8g8b8a8_premultiplied_from_float,
+ },
+ [GDK_MEMORY_B8G8R8A8] = {
+ GDK_MEMORY_ALPHA_STRAIGHT,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
+ b8g8r8a8_to_float,
+ b8g8r8a8_from_float,
+ },
+ [GDK_MEMORY_A8R8G8B8] = {
+ GDK_MEMORY_ALPHA_STRAIGHT,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
+ a8r8g8b8_to_float,
+ a8r8g8b8_from_float,
+ },
+ [GDK_MEMORY_R8G8B8A8] = {
+ GDK_MEMORY_ALPHA_STRAIGHT,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ TRUE,
+ { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
+ r8g8b8a8_to_float,
+ r8g8b8a8_from_float,
+ },
+ [GDK_MEMORY_A8B8G8R8] = {
+ GDK_MEMORY_ALPHA_STRAIGHT,
+ 4,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
+ a8b8g8r8_to_float,
+ a8b8g8r8_from_float,
+ },
+ [GDK_MEMORY_R8G8B8] = {
+ GDK_MEMORY_ALPHA_OPAQUE,
+ 3,
+ G_ALIGNOF (guchar),
+ FALSE,
+ TRUE,
+ { GL_RGBA8, GL_RGB, GL_UNSIGNED_BYTE },
+ r8g8b8_to_float,
+ r8g8b8_from_float,
+ },
+ [GDK_MEMORY_B8G8R8] = {
+ GDK_MEMORY_ALPHA_OPAQUE,
+ 3,
+ G_ALIGNOF (guchar),
+ FALSE,
+ FALSE,
+ { GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE },
+ b8g8r8_to_float,
+ b8g8r8_from_float,
+ },
+ [GDK_MEMORY_R16G16B16] = {
+ GDK_MEMORY_ALPHA_OPAQUE,
+ 6,
+ G_ALIGNOF (guint16),
+ TRUE,
+ TRUE,
+ { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT },
+ r16g16b16_to_float,
+ r16g16b16_from_float,
+ },
+ [GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 8,
+ G_ALIGNOF (guint16),
+ TRUE,
+ TRUE,
+ { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
+ r16g16b16a16_to_float,
+ r16g16b16a16_from_float,
+ },
+ [GDK_MEMORY_R16G16B16_FLOAT] = {
+ GDK_MEMORY_ALPHA_OPAQUE,
+ 6,
+ G_ALIGNOF (guint16),
+ TRUE,
+ TRUE,
+ { GL_RGB16F, GL_RGB, GL_HALF_FLOAT },
+ r16g16b16_float_to_float,
+ r16g16b16_float_from_float,
+ },
+ [GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 8,
+ G_ALIGNOF (guint16),
+ TRUE,
+ TRUE,
+ { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
+ r16g16b16a16_float_to_float,
+ r16g16b16a16_float_from_float,
+ },
+ [GDK_MEMORY_R32G32B32_FLOAT] = {
+ GDK_MEMORY_ALPHA_OPAQUE,
+ 12,
+ G_ALIGNOF (float),
+ TRUE,
+ TRUE,
+ { GL_RGB32F, GL_RGB, GL_FLOAT },
+ r32g32b32_float_to_float,
+ r32g32b32_float_from_float,
+ },
+ [GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
+ GDK_MEMORY_ALPHA_PREMULTIPLIED,
+ 16,
+ G_ALIGNOF (float),
+ TRUE,
+ TRUE,
+ { GL_RGBA32F, GL_RGBA, GL_FLOAT },
+ r32g32b32a32_float_to_float,
+ r32g32b32a32_float_from_float,
+ }
+};
+
+gsize
+gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
+{
+ return memory_formats[format].bytes_per_pixel;
+}
+
+gsize
+gdk_memory_format_alignment (GdkMemoryFormat format)
+{
+ return memory_formats[format].alignment;
+}
+
+/*<private>
+ * gdk_memory_format_prefers_high_depth:
+ * @format: a memory format
+ *
+ * Checks if the given format benefits from being rendered
+ * in bit depths higher than 8bits per pixel. See
+ * gsk_render_node_prefers_high_depth() for more information
+ * on this.
+ * Usually this is the case when
+ * gdk_memory_format_bytes_per_pixel() is larger than 4.
+ *
+ * Returns: %TRUE if the format benefits from being
+ * composited in hgiher bit depths.
+ **/
+gboolean
+gdk_memory_format_prefers_high_depth (GdkMemoryFormat format)
+{
+ return memory_formats[format].prefers_high_depth;
+}
+
+gboolean
+gdk_memory_format_gl_format (GdkMemoryFormat format,
+ gboolean gles,
+ guint *out_internal_format,
+ guint *out_format,
+ guint *out_type)
+{
+ *out_internal_format = memory_formats[format].gl.internal_format;
+ *out_format = memory_formats[format].gl.format;
+ *out_type = memory_formats[format].gl.type;
+
+ if (memory_formats[format].alpha == GDK_MEMORY_ALPHA_STRAIGHT)
+ return FALSE;
+
+ if (gles && !memory_formats[format].supports_gles)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+premultiply (float *rgba,
+ gsize n)
+{
+ for (gsize i = 0; i < n; i++)
+ {
+ rgba[0] *= rgba[3];
+ rgba[1] *= rgba[3];
+ rgba[2] *= rgba[3];
+ rgba += 4;
+ }
+}
+
+static void
+unpremultiply (float *rgba,
+ gsize n)
+{
+ for (gsize i = 0; i < n; i++)
+ {
+ if (rgba[3] > 1/255.0)
+ {
+ rgba[0] /= rgba[3];
+ rgba[1] /= rgba[3];
+ rgba[2] /= rgba[3];
+ }
+ rgba += 4;
+ }
+}
+
+void
+gdk_memory_convert (guchar *dest_data,
+ gsize dest_stride,
+ GdkMemoryFormat dest_format,
+ const guchar *src_data,
+ gsize src_stride,
+ GdkMemoryFormat src_format,
+ gsize width,
+ gsize height)
+{
+ const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
+ const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
+ float *tmp;
+ gsize y;
+
+ g_assert (dest_format < GDK_MEMORY_N_FORMATS);
+ g_assert (src_format < GDK_MEMORY_N_FORMATS);
+
+ tmp = g_new (float, width * 4);
+
+ for (y = 0; y < height; y++)
+ {
+ src_desc->to_float (tmp, src_data, width);
+ if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
+ unpremultiply (tmp, width);
+ else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
+ premultiply (tmp, width);
+ dest_desc->from_float (dest_data, tmp, width);
+ src_data += src_stride;
+ dest_data += dest_stride;
+ }
+
+ g_free (tmp);
+}
diff --git a/gdk/gdkmemoryformatprivate.h b/gdk/gdkmemoryformatprivate.h
new file mode 100644
index 0000000000..344e47fade
--- /dev/null
+++ b/gdk/gdkmemoryformatprivate.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2021 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GDK_MEMORY_CONVERT_PRIVATE_H__
+#define __GDK_MEMORY_CONVERT_PRIVATE_H__
+
+#include "gdkmemorytexture.h"
+
+G_BEGIN_DECLS
+
+gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST;
+gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST;
+gboolean gdk_memory_format_prefers_high_depth(GdkMemoryFormat format) G_GNUC_CONST;
+gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
+ gboolean gles,
+ guint *out_internal_format,
+ guint *out_format,
+ guint *out_type);
+
+void gdk_memory_convert (guchar *dest_data,
+ gsize dest_stride,
+ GdkMemoryFormat dest_format,
+ const guchar *src_data,
+ gsize src_stride,
+ GdkMemoryFormat src_format,
+ gsize width,
+ gsize height);
+
+
+G_END_DECLS
+
+#endif /* __GDK_MEMORY_CONVERT_PRIVATE_H__ */
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 6c08ef531b..52723ef805 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -20,6 +20,8 @@
#include "config.h"
#include "gdkmemorytextureprivate.h"
+
+#include "gdkmemoryformatprivate.h"
#include "gsk/ngl/fp16private.h"
/**
@@ -32,8 +34,6 @@ struct _GdkMemoryTexture
{
GdkTexture parent_instance;
- GdkMemoryFormat format;
-
GBytes *bytes;
gsize stride;
};
@@ -45,80 +45,6 @@ struct _GdkMemoryTextureClass
G_DEFINE_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK_TYPE_TEXTURE)
-gsize
-gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
-{
- switch (format)
- {
- case GDK_MEMORY_R8G8B8:
- case GDK_MEMORY_B8G8R8:
- return 3;
-
- case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
- case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
- case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
- case GDK_MEMORY_B8G8R8A8:
- case GDK_MEMORY_A8R8G8B8:
- case GDK_MEMORY_R8G8B8A8:
- case GDK_MEMORY_A8B8G8R8:
- return 4;
-
- case GDK_MEMORY_R16G16B16:
- case GDK_MEMORY_R16G16B16_FLOAT:
- return 6;
-
- case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
- case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
- return 8;
-
- case GDK_MEMORY_R32G32B32_FLOAT:
- return 12;
-
- case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
- return 16;
-
- case GDK_MEMORY_N_FORMATS:
- default:
- g_assert_not_reached ();
- return 4;
- }
-}
-
-static gsize
-gdk_memory_format_alignment (GdkMemoryFormat format)
-{
- switch (format)
- {
- case GDK_MEMORY_R8G8B8:
- case GDK_MEMORY_B8G8R8:
- case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
- case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
- case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
- case GDK_MEMORY_B8G8R8A8:
- case GDK_MEMORY_A8R8G8B8:
- case GDK_MEMORY_R8G8B8A8:
- case GDK_MEMORY_A8B8G8R8:
- return G_ALIGNOF (guchar);
-
- case GDK_MEMORY_R16G16B16:
- case GDK_MEMORY_R16G16B16_FLOAT:
- return G_ALIGNOF (guint16);
-
- case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
- case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
- return G_ALIGNOF (guint16);
-
- case GDK_MEMORY_R32G32B32_FLOAT:
- case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
- return G_ALIGNOF (float);
-
- case GDK_MEMORY_N_FORMATS:
- default:
- g_assert_not_reached ();
- return G_ALIGNOF (double);
- }
-}
-
static void
gdk_memory_texture_dispose (GObject *object)
{
@@ -143,10 +69,10 @@ gdk_memory_texture_download (GdkTexture *texture,
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
gdk_memory_convert (data, stride,
- GDK_MEMORY_CONVERT_DOWNLOAD,
+ GDK_MEMORY_DEFAULT,
(guchar *) g_bytes_get_data (self->bytes, NULL),
self->stride,
- self->format,
+ texture->format,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
@@ -158,12 +84,14 @@ gdk_memory_texture_download_float (GdkTexture *texture,
{
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
- gdk_memory_convert_to_float (data, stride,
- (guchar *) g_bytes_get_data (self->bytes, NULL),
- self->stride,
- self->format,
- gdk_texture_get_width (texture),
- gdk_texture_get_height (texture));
+ gdk_memory_convert ((guchar *) data,
+ stride * sizeof (float),
+ GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+ (guchar *) g_bytes_get_data (self->bytes, NULL),
+ self->stride,
+ texture->format,
+ gdk_texture_get_width (texture),
+ gdk_texture_get_height (texture));
}
static void
@@ -254,19 +182,13 @@ gdk_memory_texture_new (int width,
"height", height,
NULL);
- self->format = format;
+ GDK_TEXTURE (self)->format = format;
self->bytes = bytes;
self->stride = stride;
return GDK_TEXTURE (self);
}
-GdkMemoryFormat
-gdk_memory_texture_get_format (GdkMemoryTexture *self)
-{
- return self->format;
-}
-
const guchar *
gdk_memory_texture_get_data (GdkMemoryTexture *self)
{
@@ -279,429 +201,3 @@ gdk_memory_texture_get_stride (GdkMemoryTexture *self)
return self->stride;
}
-static void
-convert_memcpy (guchar *dest_data,
- gsize dest_stride,
- const guchar *src_data,
- gsize src_stride,
- gsize width,
- gsize height)
-{
- gsize y;
-
- for (y = 0; y < height; y++)
- memcpy (dest_data + y * dest_stride, src_data + y * src_stride, 4 * width);
-}
-
-#define SWIZZLE(A,R,G,B) \
-static void \
-convert_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++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- dest_data[4 * x + A] = src_data[4 * x + 0]; \
- dest_data[4 * x + R] = src_data[4 * x + 1]; \
- dest_data[4 * x + G] = src_data[4 * x + 2]; \
- dest_data[4 * x + B] = src_data[4 * x + 3]; \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}
-
-SWIZZLE(3,2,1,0)
-SWIZZLE(2,1,0,3)
-SWIZZLE(3,0,1,2)
-SWIZZLE(1,2,3,0)
-
-#define SWIZZLE_OPAQUE(A,R,G,B) \
-static void \
-convert_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++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- dest_data[4 * x + A] = 0xFF; \
- dest_data[4 * x + R] = src_data[3 * x + 0]; \
- dest_data[4 * x + G] = src_data[3 * x + 1]; \
- dest_data[4 * x + B] = src_data[3 * x + 2]; \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}
-
-SWIZZLE_OPAQUE(3,2,1,0)
-SWIZZLE_OPAQUE(3,0,1,2)
-SWIZZLE_OPAQUE(0,1,2,3)
-SWIZZLE_OPAQUE(0,3,2,1)
-
-#define PREMULTIPLY(d,c,a) G_STMT_START { guint t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
-#define SWIZZLE_PREMULTIPLY(A,R,G,B, A2,R2,G2,B2) \
-static void \
-convert_swizzle_premultiply_ ## A ## R ## G ## B ## _ ## A2 ## R2 ## G2 ## B2 \
- (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++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- dest_data[4 * x + A] = src_data[4 * x + A2]; \
- PREMULTIPLY(dest_data[4 * x + R], src_data[4 * x + R2], src_data[4 * x + A2]); \
- PREMULTIPLY(dest_data[4 * x + G], src_data[4 * x + G2], src_data[4 * x + A2]); \
- PREMULTIPLY(dest_data[4 * x + B], src_data[4 * x + B2], src_data[4 * x + A2]); \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}
-
-SWIZZLE_PREMULTIPLY (3,2,1,0, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 0,3,2,1)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 0,3,2,1)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
-
-#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
-static void \
-convert_ ## name ## _to_ ## suffix (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++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- guchar conv[4]; \
- convert_pixel_ ## name (conv, src_data + step * x); \
- dest_data[4 * x + R] = conv[0]; \
- dest_data[4 * x + G] = conv[1]; \
- dest_data[4 * x + B] = conv[2]; \
- dest_data[4 * x + A] = conv[3]; \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}
-
-#define CONVERT_FUNCS(name,step) \
-CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
-CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
-CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
-
-static inline void
-convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
-{
- const guint16 *src = (const guint16 *) src_data;
- dest_data[0] = (guchar)(src[0] >> 8);
- dest_data[1] = (guchar)(src[1] >> 8);
- dest_data[2] = (guchar)(src[2] >> 8);
- dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
-{
- const guint16 *src = (const guint16 *) src_data;
- dest_data[0] = (guchar)(src[0] >> 8);
- dest_data[1] = (guchar)(src[1] >> 8);
- dest_data[2] = (guchar)(src[2] >> 8);
- dest_data[3] = (guchar)(src[3] >> 8);
-}
-CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
-{
- float src[4];
- guint16 tmp[4];
- memcpy(tmp, src_data, sizeof(guint16) * 3);
- half_to_float4(tmp, src);
- dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
- dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
- dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
- dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
-{
- float src[4];
- half_to_float4((const guint16 *) src_data, src);
- dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
- dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
- dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
- dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
-}
-CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
-{
- float *src = (float *) src_data;
- dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
- dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
- dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
- dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
-
-static inline void
-convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
-{
- float *src = (float *) src_data;
- dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
- dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
- dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
- dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
-}
-CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
-
-typedef void (* ConversionFunc) (guchar *dest_data,
- gsize dest_stride,
- const guchar *src_data,
- gsize src_stride,
- gsize width,
- gsize height);
-
-static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
-{
- { convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
- { convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
- { convert_swizzle2103, convert_swizzle1230, convert_memcpy },
- { convert_swizzle_premultiply_3210_3210, convert_swizzle_premultiply_0123_3210, convert_swizzle_premultiply_3012_3210, },
- { convert_swizzle_premultiply_3210_0123, convert_swizzle_premultiply_0123_0123, convert_swizzle_premultiply_3012_0123 },
- { convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 },
- { 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_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
- { convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
- { convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
- { convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
- { convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
- { convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
-};
-
-void
-gdk_memory_convert (guchar *dest_data,
- gsize dest_stride,
- GdkMemoryConversion dest_format,
- const guchar *src_data,
- gsize src_stride,
- GdkMemoryFormat src_format,
- gsize width,
- gsize height)
-{
- 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);
-}
-
-#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
- for (y = 0; y < height; y++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- if (A >= 0) \
- { \
- dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
- dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
- dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
- dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
- if (premultiply) \
- { \
- dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
- dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
- dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
- } \
- } \
- else \
- { \
- dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
- dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
- dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
- dest_data[4 * x + 3] = 1.0; \
- } \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}G_STMT_END
-
-#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
- for (y = 0; y < height; y++) \
- { \
- for (x = 0; x < width; x++) \
- { \
- func (dest_data + 4 * x, src_data + step * x); \
- } \
-\
- dest_data += dest_stride; \
- src_data += src_stride; \
- } \
-}G_STMT_END
-
-static inline void
-convert_rgb16_to_float (float *dest, const guchar *src_data)
-{
- const guint16 *src = (const guint16 *) src_data;
- dest[0] = src[0] / 65535.f;
- dest[1] = src[1] / 65535.f;
- dest[2] = src[2] / 65535.f;
- dest[3] = 1.0;
-}
-
-static inline void
-convert_rgba16_to_float (float *dest, const guchar *src_data)
-{
- const guint16 *src = (const guint16 *) src_data;
- dest[0] = src[0] / 65535.f;
- dest[1] = src[1] / 65535.f;
- dest[2] = src[2] / 65535.f;
- dest[3] = src[3] / 65535.f;
-}
-
-static inline void
-convert_rgb16f_to_float (float *dest, const guchar *src_data)
-{
- guint16 tmp[4];
- memcpy(tmp, src_data, sizeof(guint16) * 3);
- tmp[3] = FP16_ONE;
- half_to_float4 (tmp, dest);
-}
-
-static inline void
-convert_rgba16f_to_float (float *dest, const guchar *src_data)
-{
- half_to_float4 ((const guint16 *) src_data, dest);
-}
-
-static inline void
-convert_rgb32f_to_float (float *dest, const guchar *src_data)
-{
- const float *src = (const float *) src_data;
- dest[0] = src[0];
- dest[1] = src[1];
- dest[2] = src[2];
- dest[3] = 1.0;
-}
-
-static inline void
-convert_rgba32f_to_float (float *dest, const guchar *src_data)
-{
- const float *src = (const float *) src_data;
- dest[0] = src[0];
- dest[1] = src[1];
- dest[2] = src[2];
- dest[3] = src[3];
-}
-
-void
-gdk_memory_convert_to_float (float *dest_data,
- gsize dest_stride,
- const guchar *src_data,
- gsize src_stride,
- GdkMemoryFormat src_format,
- gsize width,
- gsize height)
-{
- gsize x, y;
-
- switch (src_format)
- {
- case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
- CONVERT_FLOAT (2, 1, 0, 3, FALSE);
- break;
- case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
- CONVERT_FLOAT (1, 2, 3, 0, FALSE);
- break;
- case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
- CONVERT_FLOAT (0, 1, 2, 3, FALSE);
- break;
- case GDK_MEMORY_B8G8R8A8:
- CONVERT_FLOAT (2, 1, 0, 3, TRUE);
- break;
- case GDK_MEMORY_A8R8G8B8:
- CONVERT_FLOAT (1, 2, 3, 0, TRUE);
- break;
- case GDK_MEMORY_R8G8B8A8:
- CONVERT_FLOAT (0, 1, 2, 3, TRUE);
- break;
- case GDK_MEMORY_A8B8G8R8:
- CONVERT_FLOAT (3, 2, 1, 0, TRUE);
- break;
- case GDK_MEMORY_R8G8B8:
- CONVERT_FLOAT (0, 1, 2, -1, FALSE);
- break;
- case GDK_MEMORY_B8G8R8:
- CONVERT_FLOAT (2, 1, 0, -1, FALSE);
- break;
- case GDK_MEMORY_R16G16B16:
- CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
- break;
- case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
- CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
- break;
- case GDK_MEMORY_R16G16B16_FLOAT:
- CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
- break;
- case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
- CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
- break;
- case GDK_MEMORY_R32G32B32_FLOAT:
- CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
- break;
- case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
- CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
- break;
-
- case GDK_MEMORY_N_FORMATS:
- default:
- g_assert_not_reached();
- }
-}
diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h
index ddd9fd1c37..0cd5e91f27 100644
--- a/gdk/gdkmemorytextureprivate.h
+++ b/gdk/gdkmemorytextureprivate.h
@@ -29,45 +29,9 @@ G_BEGIN_DECLS
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
-typedef enum {
- GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
- GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
- GDK_MEMORY_CONVERT_GLES_RGBA,
-
- GDK_MEMORY_N_CONVERSIONS
-} GdkMemoryConversion;
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
-#else
-#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
-#endif
-
-gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format);
-
-GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *self);
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
-void gdk_memory_convert (guchar *dest_data,
- gsize dest_stride,
- GdkMemoryConversion dest_format,
- const guchar *src_data,
- gsize src_stride,
- GdkMemoryFormat src_format,
- gsize width,
- gsize height);
-
-void gdk_memory_convert_to_float (float *dest_data,
- gsize dest_stride,
- const guchar *src_data,
- gsize src_stride,
- GdkMemoryFormat src_format,
- gsize width,
- gsize height);
-
G_END_DECLS
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 13d779a817..40d9c21b8f 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -71,7 +71,7 @@ struct _GdkSurfacePrivate
gpointer egl_native_window;
#ifdef HAVE_EGL
EGLSurface egl_surface;
- gboolean egl_surface_hdr;
+ gboolean egl_surface_high_depth;
#endif
gpointer widget;
@@ -1109,16 +1109,16 @@ gdk_surface_get_egl_surface (GdkSurface *self)
void
gdk_surface_ensure_egl_surface (GdkSurface *self,
- gboolean hdr)
+ gboolean high_depth)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
GdkDisplay *display = gdk_surface_get_display (self);
g_return_if_fail (priv->egl_native_window != NULL);
- if (priv->egl_surface_hdr != hdr &&
+ if (priv->egl_surface_high_depth != high_depth &&
priv->egl_surface != NULL &&
- gdk_display_get_egl_config_hdr (display) != gdk_display_get_egl_config (display))
+ gdk_display_get_egl_config_high_depth (display) != gdk_display_get_egl_config (display))
{
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
priv->egl_surface = NULL;
@@ -1127,11 +1127,11 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
if (priv->egl_surface == NULL)
{
priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
- hdr ? gdk_display_get_egl_config_hdr (display)
- : gdk_display_get_egl_config (display),
+ high_depth ? gdk_display_get_egl_config_high_depth (display)
+ : gdk_display_get_egl_config (display),
(EGLNativeWindowType) priv->egl_native_window,
NULL);
- priv->egl_surface_hdr = hdr;
+ priv->egl_surface_high_depth = high_depth;
}
#endif
}
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index b79b671a53..f4c5928c8d 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -808,6 +808,12 @@ gdk_texture_download_texture (GdkTexture *texture)
return texture;
}
+GdkMemoryFormat
+gdk_texture_get_format (GdkTexture *self)
+{
+ return self->format;
+}
+
gboolean
gdk_texture_set_render_data (GdkTexture *self,
gpointer key,
@@ -972,4 +978,3 @@ gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
return gdk_save_tiff (texture);
}
-
diff --git a/gdk/gdktextureprivate.h b/gdk/gdktextureprivate.h
index 814ed5d92c..994c9901f8 100644
--- a/gdk/gdktextureprivate.h
+++ b/gdk/gdktextureprivate.h
@@ -3,6 +3,8 @@
#include "gdktexture.h"
+#include "gdkmemorytexture.h"
+
G_BEGIN_DECLS
#define GDK_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_TEXTURE, GdkTextureClass))
@@ -13,6 +15,7 @@ struct _GdkTexture
{
GObject parent_instance;
+ GdkMemoryFormat format;
int width;
int height;
@@ -42,6 +45,7 @@ cairo_surface_t * gdk_texture_download_surface (GdkTexture
/* NB: GdkMemoryTexture */
GdkTexture * gdk_texture_download_texture (GdkTexture *texture);
+GdkMemoryFormat gdk_texture_get_format (GdkTexture *self);
gboolean gdk_texture_set_render_data (GdkTexture *self,
gpointer key,
gpointer data,
diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c
index 2466c317b8..20c1860645 100644
--- a/gdk/gdkvulkancontext.c
+++ b/gdk/gdkvulkancontext.c
@@ -425,7 +425,7 @@ device_supports_incremental_present (VkPhysicalDevice device)
static void
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c
index 97e6dfffd0..9bdc5e3a43 100644
--- a/gdk/loaders/gdkpng.c
+++ b/gdk/loaders/gdkpng.c
@@ -20,6 +20,7 @@
#include "gdkpngprivate.h"
#include "gdkintl.h"
+#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdktexture.h"
@@ -480,7 +481,7 @@ gdk_save_png (GdkTexture *texture)
height = gdk_texture_get_height (texture);
mtexture = gdk_texture_download_texture (texture);
- format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (mtexture));
+ format = gdk_texture_get_format (mtexture);
switch (format)
{
diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c
index d7416391ee..d2d8dfdbde 100644
--- a/gdk/loaders/gdktiff.c
+++ b/gdk/loaders/gdktiff.c
@@ -20,6 +20,7 @@
#include "gdktiffprivate.h"
#include "gdkintl.h"
+#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdktexture.h"
@@ -283,7 +284,7 @@ gdk_save_tiff (GdkTexture *texture)
height = gdk_texture_get_height (texture);
memory_texture = gdk_texture_download_texture (texture);
- format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (memory_texture));
+ format = gdk_texture_get_format (memory_texture);
for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
{
diff --git a/gdk/macos/gdkmacoscairocontext.c b/gdk/macos/gdkmacoscairocontext.c
index 7a195ab063..73ba7cffa0 100644
--- a/gdk/macos/gdkmacoscairocontext.c
+++ b/gdk/macos/gdkmacoscairocontext.c
@@ -82,7 +82,7 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
static void
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index 967648626c..313be91fb9 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -291,7 +291,7 @@ opaque_region_covers_surface (GdkMacosGLContext *self)
static void
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *painted)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
@@ -345,7 +345,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
[self->gl_context update];
}
- GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, request_hdr, painted);
+ GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, painted);
if (!self->is_attached)
{
diff --git a/gdk/meson.build b/gdk/meson.build
index 06905233f8..0756f7667c 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -30,6 +30,7 @@ gdk_public_sources = files([
'gdkhsla.c',
'gdkkeys.c',
'gdkkeyuni.c',
+ 'gdkmemoryformat.c',
'gdkmemorytexture.c',
'gdkmonitor.c',
'gdkpaintable.c',
diff --git a/gdk/wayland/gdkcairocontext-wayland.c b/gdk/wayland/gdkcairocontext-wayland.c
index e06eaa1096..e05ea6a7d9 100644
--- a/gdk/wayland/gdkcairocontext-wayland.c
+++ b/gdk/wayland/gdkcairocontext-wayland.c
@@ -144,7 +144,7 @@ gdk_wayland_cairo_context_create_surface (GdkWaylandCairoContext *self)
static void
gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context);
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 9fc887367a..d631816286 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -47,12 +47,12 @@ G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
static void
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
gdk_wayland_surface_ensure_wl_egl_window (gdk_draw_context_get_surface (draw_context));
- GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, request_hdr, region);
+ GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, prefers_high_depth, region);
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
}
diff --git a/gdk/win32/gdkcairocontext-win32.c b/gdk/win32/gdkcairocontext-win32.c
index 65aef46b48..480baf7802 100644
--- a/gdk/win32/gdkcairocontext-win32.c
+++ b/gdk/win32/gdkcairocontext-win32.c
@@ -53,7 +53,7 @@ create_cairo_surface_for_surface (GdkSurface *surface,
static void
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
diff --git a/gdk/win32/gdkglcontext-win32-egl.c b/gdk/win32/gdkglcontext-win32-egl.c
index 8d6bef9e17..1507dd8225 100644
--- a/gdk/win32/gdkglcontext-win32-egl.c
+++ b/gdk/win32/gdkglcontext-win32-egl.c
@@ -471,12 +471,12 @@ gdk_win32_gl_context_egl_make_current (GdkGLContext *context,
static void
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *update_area)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
- GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, request_hdr, update_area);
+ GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
}
static void
diff --git a/gdk/win32/gdkglcontext-win32-wgl.c b/gdk/win32/gdkglcontext-win32-wgl.c
index 9f9bc257a3..ea5f377966 100644
--- a/gdk/win32/gdkglcontext-win32-wgl.c
+++ b/gdk/win32/gdkglcontext-win32-wgl.c
@@ -118,12 +118,12 @@ gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
static void
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *update_area)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
- GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, request_hdr, update_area);
+ GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
}
static int
diff --git a/gdk/win32/gdkvulkancontext-win32.c b/gdk/win32/gdkvulkancontext-win32.c
index d82cb15d27..894bbfa548 100644
--- a/gdk/win32/gdkvulkancontext-win32.c
+++ b/gdk/win32/gdkvulkancontext-win32.c
@@ -68,12 +68,12 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
static void
gdk_win32_vulkan_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *update_area)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
- GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, request_hdr, update_area);
+ GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
}
static void
diff --git a/gdk/x11/gdkcairocontext-x11.c b/gdk/x11/gdkcairocontext-x11.c
index e6accbb6ad..e25ec197a7 100644
--- a/gdk/x11/gdkcairocontext-x11.c
+++ b/gdk/x11/gdkcairocontext-x11.c
@@ -55,7 +55,7 @@ create_cairo_surface_for_surface (GdkSurface *surface)
static void
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
diff --git a/gdk/x11/gdkglcontext-egl.c b/gdk/x11/gdkglcontext-egl.c
index 39255ac881..67d730fcfb 100644
--- a/gdk/x11/gdkglcontext-egl.c
+++ b/gdk/x11/gdkglcontext-egl.c
@@ -61,10 +61,10 @@ gdk_x11_display_get_egl_display (GdkDisplay *display)
static void
gdk_x11_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
- gboolean request_hdr,
+ gboolean prefers_high_depth,
cairo_region_t *region)
{
- GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->begin_frame (draw_context, request_hdr, region);
+ GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->begin_frame (draw_context, prefers_high_depth, region);
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
}
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 9c4332fe01..6381d334d8 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -725,3 +725,8 @@ gsk_value_dup_render_node (const GValue *value)
return gsk_render_node_ref (value->data[0].v_pointer);
}
+gboolean
+gsk_render_node_prefers_high_depth (const GskRenderNode *node)
+{
+ return node->prefers_high_depth;
+}
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index fd2a9e5d44..28cb14ae64 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -28,6 +28,7 @@
#include "gsktransformprivate.h"
#include "gdk/gdktextureprivate.h"
+#include "gdk/gdkmemoryformatprivate.h"
#include "gdk/gdk-private.h"
#include <hb-ot.h>
@@ -1560,6 +1561,8 @@ gsk_texture_node_new (GdkTexture *texture,
self->texture = g_object_ref (texture);
graphene_rect_init_from_rect (&node->bounds, bounds);
+ node->prefers_high_depth = gdk_memory_format_prefers_high_depth (gdk_texture_get_format (texture));
+
return node;
}
@@ -2730,11 +2733,13 @@ gsk_container_node_new (GskRenderNode **children,
self->children[0] = gsk_render_node_ref (children[0]);
graphene_rect_init_from_rect (&bounds, &(children[0]->bounds));
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (children[0]);
for (guint i = 1; i < n_children; i++)
{
self->children[i] = gsk_render_node_ref (children[i]);
graphene_rect_union (&bounds, &(children[i]->bounds), &bounds);
+ node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
}
graphene_rect_init_from_rect (&node->bounds, &bounds);
@@ -2965,6 +2970,8 @@ gsk_transform_node_new (GskRenderNode *child,
&child->bounds,
&node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3100,6 +3107,8 @@ gsk_opacity_node_new (GskRenderNode *child,
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3302,6 +3311,8 @@ gsk_color_matrix_node_new (GskRenderNode *child,
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3451,6 +3462,8 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
else
graphene_rect_init_from_rect (&self->child_bounds, &child->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3582,6 +3595,8 @@ gsk_clip_node_new (GskRenderNode *child,
graphene_rect_intersection (&self->clip, &child->bounds, &node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3713,6 +3728,8 @@ gsk_rounded_clip_node_new (GskRenderNode *child,
graphene_rect_intersection (&self->clip.bounds, &child->bounds, &node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -3932,6 +3949,8 @@ gsk_shadow_node_new (GskRenderNode *child,
gsk_shadow_node_get_bounds (self, &node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -4125,6 +4144,8 @@ gsk_blend_node_new (GskRenderNode *bottom,
graphene_rect_union (&bottom->bounds, &top->bounds, &node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (bottom) || gsk_render_node_prefers_high_depth (top);
+
return node;
}
@@ -4273,6 +4294,8 @@ gsk_cross_fade_node_new (GskRenderNode *start,
graphene_rect_union (&start->bounds, &end->bounds, &node->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (start) || gsk_render_node_prefers_high_depth (end);
+
return node;
}
@@ -4864,6 +4887,8 @@ gsk_blur_node_new (GskRenderNode *child,
- clip_radius,
- clip_radius);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -4986,6 +5011,8 @@ gsk_debug_node_new (GskRenderNode *child,
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
+ node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
+
return node;
}
@@ -5150,7 +5177,10 @@ gsk_gl_shader_node_new (GskGLShader *shader,
{
self->children = g_malloc_n (n_children, sizeof (GskRenderNode *));
for (guint i = 0; i < n_children; i++)
- self->children[i] = gsk_render_node_ref (children[i]);
+ {
+ self->children[i] = gsk_render_node_ref (children[i]);
+ node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
+ }
}
return node;
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index ac20813b65..cdb75afd2f 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -27,6 +27,8 @@ struct _GskRenderNode
gatomicrefcount ref_count;
graphene_rect_t bounds;
+
+ guint prefers_high_depth : 1;
};
struct _GskRenderNodeClass
@@ -109,6 +111,7 @@ GskRenderNode ** gsk_container_node_get_children (const GskRenderNode *no
void gsk_transform_node_get_translate (const GskRenderNode *node,
float *dx,
float *dy);
+gboolean gsk_render_node_prefers_high_depth (const GskRenderNode *node);
G_END_DECLS
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index a5fbf0dc8d..8dde9ff269 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkmemorytextureprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include <gsk/gskdebugprivate.h>
@@ -1231,6 +1232,7 @@ gboolean
gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
guint *out_fbo_id,
@@ -1247,6 +1249,7 @@ gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
texture_id = gsk_ngl_command_queue_create_texture (self,
width, height,
+ format,
min_filter, mag_filter);
if (texture_id == -1)
@@ -1272,6 +1275,7 @@ int
gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter)
{
@@ -1296,9 +1300,9 @@ gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (gdk_gl_context_get_use_es (self->context))
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
else
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
/* Restore the previous texture if it was set */
if (self->attachments->textures[0].id != 0)
@@ -1353,7 +1357,7 @@ gsk_ngl_command_queue_upload_texture (GskNglCommandQueue *self,
height = MAX (height, self->max_texture_size);
}
- texture_id = gsk_ngl_command_queue_create_texture (self, width, height, min_filter, mag_filter);
+ texture_id = gsk_ngl_command_queue_create_texture (self, width, height, GL_RGBA8, min_filter, mag_filter);
if (texture_id == -1)
return texture_id;
@@ -1361,7 +1365,7 @@ gsk_ngl_command_queue_upload_texture (GskNglCommandQueue *self,
{
GdkMemoryTexture *memory_texture = GDK_MEMORY_TEXTURE (texture);
data = gdk_memory_texture_get_data (memory_texture);
- data_format = gdk_memory_texture_get_format (memory_texture);
+ data_format = gdk_texture_get_format (texture);
data_stride = gdk_memory_texture_get_stride (memory_texture);
}
else
diff --git a/gsk/ngl/gsknglcommandqueueprivate.h b/gsk/ngl/gsknglcommandqueueprivate.h
index b13838d48e..40cca01162 100644
--- a/gsk/ngl/gsknglcommandqueueprivate.h
+++ b/gsk/ngl/gsknglcommandqueueprivate.h
@@ -290,12 +290,14 @@ int gsk_ngl_command_queue_upload_texture (GskNglCommandQue
int gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter);
guint gsk_ngl_command_queue_create_framebuffer (GskNglCommandQueue *self);
gboolean gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
guint *out_fbo_id,
diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c
index 3bf4ace071..87f2864241 100644
--- a/gsk/ngl/gskngldriver.c
+++ b/gsk/ngl/gskngldriver.c
@@ -183,6 +183,7 @@ gsk_ngl_driver_create_atlas (GskNglDriver *self)
atlas->texture_id = gsk_ngl_command_queue_create_texture (self->command_queue,
atlas->width,
atlas->height,
+ GL_RGBA8,
GL_LINEAR,
GL_LINEAR);
@@ -750,6 +751,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
guint texture_id;
int height;
int width;
+ int format;
g_return_val_if_fail (GSK_IS_NGL_DRIVER (self), 0);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
@@ -757,6 +759,8 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
context = self->command_queue->context;
+ format = GL_RGBA8;
+
if (GDK_IS_GL_TEXTURE (texture))
{
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
@@ -799,7 +803,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
mag_filter);
t = gsk_ngl_texture_new (texture_id,
- width, height, min_filter, mag_filter,
+ width, height, format, min_filter, mag_filter,
self->current_frame_id);
g_hash_table_insert (self->textures, GUINT_TO_POINTER (texture_id), t);
@@ -820,6 +824,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
* @self: a `GskNglDriver`
* @width: the width of the texture
* @height: the height of the texture
+ * @format: format for the texture
* @min_filter: GL_NEAREST or GL_LINEAR
* @mag_filter: GL_NEAREST or GL_FILTER
*
@@ -827,6 +832,8 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
* to upload data, map to a framebuffer, or other uses which may
* modify the texture immediately.
*
+ * Typical examples for @format are GK_RGBA8, GL_RGBA16F or GL_RGBA32F.
+ *
* Use gsk_ngl_driver_release_texture() to release this texture back into
* the pool so it may be reused later in the pipeline.
*
@@ -837,6 +844,7 @@ GskNglTexture *
gsk_ngl_driver_create_texture (GskNglDriver *self,
float width,
float height,
+ int format,
int min_filter,
int mag_filter)
{
@@ -847,9 +855,11 @@ gsk_ngl_driver_create_texture (GskNglDriver *self,
texture_id = gsk_ngl_command_queue_create_texture (self->command_queue,
width, height,
+ format,
min_filter, mag_filter);
texture = gsk_ngl_texture_new (texture_id,
width, height,
+ format,
min_filter, mag_filter,
self->current_frame_id);
g_hash_table_insert (self->textures,
@@ -896,6 +906,7 @@ gsk_ngl_driver_release_texture (GskNglDriver *self,
* @self: a `GskNglDriver`
* @width: the width for the render target
* @height: the height for the render target
+ * @format: the format to use
* @min_filter: the min filter to use for the texture
* @mag_filter: the mag filter to use for the texture
* @out_render_target: (out): a location for the render target
@@ -904,6 +915,8 @@ gsk_ngl_driver_release_texture (GskNglDriver *self,
* bound to that framebuffer of the size @width x @height and using the
* appropriate filters.
*
+ * Typical examples for @format are GK_RGBA8, GL_RGBA16F or GL_RGBA32F.
+ *
* Use gsk_ngl_driver_release_render_target() when you are finished with
* the render target to release it. You may steal the texture from the
* render target when releasing it.
@@ -915,6 +928,7 @@ gboolean
gsk_ngl_driver_create_render_target (GskNglDriver *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
GskNglRenderTarget **out_render_target)
@@ -947,6 +961,7 @@ gsk_ngl_driver_create_render_target (GskNglDriver *self,
if (gsk_ngl_command_queue_create_render_target (self->command_queue,
width, height,
+ format,
min_filter, mag_filter,
&framebuffer_id, &texture_id))
{
@@ -955,6 +970,7 @@ gsk_ngl_driver_create_render_target (GskNglDriver *self,
render_target = g_slice_new0 (GskNglRenderTarget);
render_target->min_filter = min_filter;
render_target->mag_filter = mag_filter;
+ render_target->format = format;
render_target->width = width;
render_target->height = height;
render_target->framebuffer_id = framebuffer_id;
@@ -1014,6 +1030,7 @@ gsk_ngl_driver_release_render_target (GskNglDriver *self,
texture = gsk_ngl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
+ render_target->format,
render_target->min_filter,
render_target->mag_filter,
self->current_frame_id);
@@ -1266,6 +1283,7 @@ gsk_ngl_driver_add_texture_slices (GskNglDriver *self,
/* Allocate one Texture for the entire thing. */
t = gsk_ngl_texture_new (0,
tex_width, tex_height,
+ GL_RGBA8,
GL_NEAREST, GL_NEAREST,
self->current_frame_id);
diff --git a/gsk/ngl/gskngldriverprivate.h b/gsk/ngl/gskngldriverprivate.h
index 9d40c81b2b..42b6263ec1 100644
--- a/gsk/ngl/gskngldriverprivate.h
+++ b/gsk/ngl/gskngldriverprivate.h
@@ -88,6 +88,7 @@ struct _GskNglRenderTarget
guint texture_id;
int min_filter;
int mag_filter;
+ int format;
int width;
int height;
};
@@ -144,6 +145,7 @@ GdkGLContext *gsk_ngl_driver_get_context (GskNglDriver
gboolean gsk_ngl_driver_create_render_target (GskNglDriver *self,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
GskNglRenderTarget **render_target);
@@ -166,6 +168,7 @@ guint gsk_ngl_driver_load_texture (GskNglDriver
GskNglTexture *gsk_ngl_driver_create_texture (GskNglDriver *self,
float width,
float height,
+ int format,
int min_filter,
int mag_filter);
void gsk_ngl_driver_release_texture (GskNglDriver *self,
diff --git a/gsk/ngl/gsknglglyphlibrary.c b/gsk/ngl/gsknglglyphlibrary.c
index 33c86cc967..ede4f19105 100644
--- a/gsk/ngl/gsknglglyphlibrary.c
+++ b/gsk/ngl/gsknglglyphlibrary.c
@@ -21,7 +21,7 @@
#include "config.h"
#include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include "gsknglcommandqueueprivate.h"
@@ -237,7 +237,7 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary *self,
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data,
width * 4,
- GDK_MEMORY_CONVERT_GLES_RGBA,
+ GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
cairo_image_surface_get_data (surface),
width * 4,
GDK_MEMORY_DEFAULT,
diff --git a/gsk/ngl/gskngliconlibrary.c b/gsk/ngl/gskngliconlibrary.c
index ab4d1b4d6f..cfc662a9e6 100644
--- a/gsk/ngl/gskngliconlibrary.c
+++ b/gsk/ngl/gskngliconlibrary.c
@@ -21,7 +21,7 @@
#include "config.h"
#include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdktextureprivate.h>
@@ -115,7 +115,7 @@ gsk_ngl_icon_library_add (GskNglIconLibrary *self,
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
- GDK_MEMORY_CONVERT_GLES_RGBA,
+ GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
surface_data, cairo_image_surface_get_stride (surface),
GDK_MEMORY_DEFAULT, width, height);
gl_format = GL_RGBA;
diff --git a/gsk/ngl/gsknglrenderer.c b/gsk/ngl/gsknglrenderer.c
index cdb6717043..eea48b6e6d 100644
--- a/gsk/ngl/gsknglrenderer.c
+++ b/gsk/ngl/gsknglrenderer.c
@@ -22,8 +22,11 @@
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdkdisplayprivate.h>
+#include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdksurfaceprivate.h>
#include <gsk/gskdebugprivate.h>
#include <gsk/gskrendererprivate.h>
+#include <gsk/gskrendernodeprivate.h>
#include "gsknglcommandqueueprivate.h"
#include "gskngldriverprivate.h"
@@ -201,7 +204,9 @@ gsk_ngl_renderer_render (GskRenderer *renderer,
viewport.size.height = gdk_surface_get_height (surface) * scale_factor;
gdk_gl_context_make_current (self->context);
- gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->context), update_area);
+ gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->context),
+ gsk_render_node_prefers_high_depth (root),
+ update_area);
/* Must be called *AFTER* gdk_draw_context_begin_frame() */
render_region = get_render_region (surface, self->context);
@@ -236,6 +241,7 @@ gsk_ngl_renderer_render_texture (GskRenderer *renderer,
guint texture_id;
int width;
int height;
+ int format;
g_assert (GSK_IS_NGL_RENDERER (renderer));
g_assert (root != NULL);
@@ -243,8 +249,11 @@ gsk_ngl_renderer_render_texture (GskRenderer *renderer,
width = ceilf (viewport->size.width);
height = ceilf (viewport->size.height);
+ format = gsk_render_node_prefers_high_depth (root) ? GL_RGBA32F : GL_RGBA8;
+
if (gsk_ngl_driver_create_render_target (self->driver,
width, height,
+ format,
GL_NEAREST, GL_NEAREST,
&render_target))
{
diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c
index baf87f6461..e3436e10f4 100644
--- a/gsk/ngl/gsknglrenderjob.c
+++ b/gsk/ngl/gsknglrenderjob.c
@@ -162,6 +162,11 @@ struct _GskNglRenderJob
/* If we should be rendering red zones over fallback nodes */
guint debug_fallback : 1;
+
+ /* Format we want to use for intermediate textures, determined by
+ * looking at the format of the framebuffer we are rendering on.
+ */
+ int target_format;
};
typedef struct _GskNglRenderOffscreen
@@ -198,6 +203,16 @@ static gboolean gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob
const GskRenderNode *node,
GskNglRenderOffscreen *offscreen);
+static inline int
+get_target_format (GskNglRenderJob *job,
+ const GskRenderNode *node)
+{
+ if (gsk_render_node_prefers_high_depth (node))
+ return job->target_format;
+
+ return GL_RGBA8;
+}
+
static inline void
init_full_texture_region (GskNglRenderOffscreen *offscreen)
{
@@ -1258,6 +1273,7 @@ blur_offscreen (GskNglRenderJob *job,
if (!gsk_ngl_driver_create_render_target (job->driver,
MAX (texture_to_blur_width, 1),
MAX (texture_to_blur_height, 1),
+ job->target_format,
GL_NEAREST, GL_NEAREST,
&pass1))
return 0;
@@ -1268,6 +1284,7 @@ blur_offscreen (GskNglRenderJob *job,
if (!gsk_ngl_driver_create_render_target (job->driver,
texture_to_blur_width,
texture_to_blur_height,
+ job->target_format,
GL_NEAREST, GL_NEAREST,
&pass2))
return gsk_ngl_driver_release_render_target (job->driver, pass1, FALSE);
@@ -2179,6 +2196,7 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job,
if (!gsk_ngl_driver_create_render_target (job->driver,
texture_width, texture_height,
+ get_target_format (job, node),
GL_NEAREST, GL_NEAREST,
&render_target))
g_assert_not_reached ();
@@ -2449,6 +2467,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job,
gsk_ngl_driver_create_render_target (job->driver,
texture_width, texture_height,
+ get_target_format (job, node),
GL_NEAREST, GL_NEAREST,
&render_target);
@@ -3856,6 +3875,7 @@ gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob *job,
if (!gsk_ngl_driver_create_render_target (job->driver,
scaled_width, scaled_height,
+ get_target_format (job, node),
filter, filter,
&render_target))
g_assert_not_reached ();
@@ -3954,6 +3974,7 @@ gsk_ngl_render_job_render_flipped (GskNglRenderJob *job,
if (!gsk_ngl_command_queue_create_render_target (job->command_queue,
MAX (1, job->viewport.size.width),
MAX (1, job->viewport.size.height),
+ job->target_format,
GL_NEAREST, GL_NEAREST,
&framebuffer_id, &texture_id))
return;
@@ -4044,6 +4065,22 @@ gsk_ngl_render_job_set_debug_fallback (GskNglRenderJob *job,
job->debug_fallback = !!debug_fallback;
}
+static int
+get_framebuffer_format (guint framebuffer)
+{
+ int size;
+
+ glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
+ glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size);
+
+ if (size >= 32)
+ return GL_RGBA32F;
+ else if (size >= 16)
+ return GL_RGBA16F;
+ else
+ return GL_RGBA8;
+}
+
GskNglRenderJob *
gsk_ngl_render_job_new (GskNglDriver *driver,
const graphene_rect_t *viewport,
@@ -4070,6 +4107,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver,
job->scale_x = scale_factor;
job->scale_y = scale_factor;
job->viewport = *viewport;
+ job->target_format = get_framebuffer_format (framebuffer);
gsk_ngl_render_job_set_alpha (job, 1.0f);
gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL);
diff --git a/gsk/ngl/gskngltexture.c b/gsk/ngl/gskngltexture.c
index 5ee38f69b6..c70d4d91b2 100644
--- a/gsk/ngl/gskngltexture.c
+++ b/gsk/ngl/gskngltexture.c
@@ -59,6 +59,7 @@ GskNglTexture *
gsk_ngl_texture_new (guint texture_id,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
gint64 frame_id)
@@ -70,6 +71,7 @@ gsk_ngl_texture_new (guint texture_id,
texture->link.data = texture;
texture->min_filter = min_filter;
texture->mag_filter = mag_filter;
+ texture->format = format;
texture->width = width;
texture->height = height;
texture->last_used_in_frame = frame_id;
diff --git a/gsk/ngl/gskngltexturelibrary.c b/gsk/ngl/gskngltexturelibrary.c
index 7998ae9850..03b8e252f7 100644
--- a/gsk/ngl/gskngltexturelibrary.c
+++ b/gsk/ngl/gskngltexturelibrary.c
@@ -228,7 +228,7 @@ gsk_ngl_texture_library_pack_one (GskNglTextureLibrary *self,
height = MIN (height, self->driver->command_queue->max_texture_size);
}
- texture = gsk_ngl_driver_create_texture (self->driver, width, height, GL_LINEAR, GL_LINEAR);
+ texture = gsk_ngl_driver_create_texture (self->driver, width, height, GL_RGBA8, GL_LINEAR, GL_LINEAR);
texture->permanent = TRUE;
return texture;
diff --git a/gsk/ngl/gskngltextureprivate.h b/gsk/ngl/gskngltextureprivate.h
index 1d9052f625..55ef48c4d3 100644
--- a/gsk/ngl/gskngltextureprivate.h
+++ b/gsk/ngl/gskngltextureprivate.h
@@ -67,6 +67,7 @@ struct _GskNglTexture
int height;
int min_filter;
int mag_filter;
+ int format;
/* Set when used by an atlas so we don't drop the texture */
guint permanent : 1;
@@ -75,6 +76,7 @@ struct _GskNglTexture
GskNglTexture *gsk_ngl_texture_new (guint texture_id,
int width,
int height,
+ int format,
int min_filter,
int mag_filter,
gint64 frame_id);
diff --git a/testsuite/gdk/texture.c b/testsuite/gdk/texture.c
index fc1f728c7c..1a218ddd4a 100644
--- a/testsuite/gdk/texture.c
+++ b/testsuite/gdk/texture.c
@@ -1,6 +1,6 @@
#include <gtk.h>
-static gboolean
+static void
compare_pixels (int width,
int height,
guchar *data1,
@@ -8,15 +8,17 @@ compare_pixels (int width,
guchar *data2,
gsize stride2)
{
- int i;
- for (i = 0; i < height; i++)
+ int x, y;
+ for (y = 0; y < height; y++)
{
- gconstpointer p1 = data1 + i * stride1;
- gconstpointer p2 = data2 + i * stride2;
- if (memcmp (p1, p2, width * 4) != 0)
- return FALSE;
+ const guint32 *p1 = (const guint32*) (data1 + y * stride1);
+ const guint32 *p2 = (const guint32*) (data2 + y * stride2);
+
+ for (x = 0; x < width; x++)
+ {
+ g_assert_cmphex (p1[x], ==, p2[x]);
+ }
}
- return TRUE;
}
static void
@@ -55,10 +57,10 @@ test_texture_from_pixbuf (void)
cairo_paint (cr);
cairo_destroy (cr);
- g_assert_true (compare_pixels (width, height,
- data, stride,
- cairo_image_surface_get_data (surface),
- cairo_image_surface_get_stride (surface)));
+ compare_pixels (width, height,
+ data, stride,
+ cairo_image_surface_get_data (surface),
+ cairo_image_surface_get_stride (surface));
g_free (data);