From 7a11bc9442a0ab7db38a18edce2ae2a181944423 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 2 Oct 2023 23:16:42 -0400 Subject: [PATCH] display: Get supported dmabuf formats These are the dmabuf formats that we can hope to download by first importing them as an EGLImage and then downloading them as a GL texture. --- gdk/gdkdisplay.c | 95 +++++++++++++++++++++++++++++++++++++++++ gdk/gdkdisplay.h | 11 +++++ gdk/gdkdisplayprivate.h | 3 ++ 3 files changed, 109 insertions(+) diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 3ea82a5743..2518cf91e4 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -404,6 +404,8 @@ gdk_display_finalize (GObject *object) g_list_free_full (display->seats, g_object_unref); + g_free (display->egl_dmabuf_formats); + G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object); } @@ -1259,6 +1261,61 @@ gdk_display_create_vulkan_context (GdkDisplay *self, NULL); } +static void +init_dmabuf_formats (GdkDisplay *self) +{ + GdkDisplayPrivate *priv = gdk_display_get_instance_private (self); + + if (priv->egl_display != EGL_NO_DISPLAY) + { + int num_formats; + int *formats; + GArray *array; + + eglQueryDmaBufFormatsEXT (priv->egl_display, 0, NULL, &num_formats); + formats = g_new (int, num_formats); + eglQueryDmaBufFormatsEXT (priv->egl_display, num_formats, formats, &num_formats); + + array = g_array_new (FALSE, FALSE, sizeof (GdkDmabufFormat)); + + for (int i = 0; i < num_formats; i++) + { + int num_modifiers; + uint64_t *modifiers; + unsigned int *external_only; + + eglQueryDmaBufModifiersEXT (priv->egl_display, formats[i], 0, NULL, NULL, &num_modifiers); + modifiers = g_new (uint64_t, num_modifiers); + external_only = g_new (unsigned int, num_modifiers); + eglQueryDmaBufModifiersEXT (priv->egl_display, formats[i], num_modifiers, modifiers, external_only, &num_modifiers); + + if (num_modifiers == 0) + g_array_append_val (array, ((GdkDmabufFormat){ formats[i], 0 })); + else + { + for (int j = 0; j < num_modifiers; j++) + g_array_append_val (array, ((GdkDmabufFormat){ formats[i], modifiers[j] })); + } + + g_free (modifiers); + } + + g_free (formats); + + self->egl_dmabuf_n_formats = array->len; + self->egl_dmabuf_formats = (GdkDmabufFormat *) g_array_free (array, FALSE); + } + + GDK_DEBUG (MISC, "EGL dmabuf formats: (%lu)", self->egl_dmabuf_n_formats); + for (gsize i = 0; i < self->egl_dmabuf_n_formats; i++) + { + uint32_t f = self->egl_dmabuf_formats[i].fourcc; + uint64_t m = self->egl_dmabuf_formats[i].modifier; + + GDK_DEBUG (MISC, " %c%c%c%c:%#lx", f & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff, m); + } +} + static void gdk_display_init_gl (GdkDisplay *self) { @@ -1300,6 +1357,10 @@ gdk_display_init_gl (GdkDisplay *self) gdk_gl_backend_use (GDK_GL_CONTEXT_GET_CLASS (context)->backend_type); gdk_profiler_end_mark (before, "initialize OpenGL", NULL); + + gdk_gl_context_make_current (context); + + init_dmabuf_formats (self); } /** @@ -1824,6 +1885,40 @@ gdk_display_get_egl_display (GdkDisplay *self) #endif } +/** + * GdkDmabufFormat: + * @fourcc: the format code + * @modifiers: the format modifier + * + * The `GdkDmabufFormat` struct represents a dma-buf format + * as defined in the `drm_fourcc.h` header. + * + * Since: 4.14 + */ + +/** + * gdk_display_get_dmabuf_formats: + * @display: a `GdkDisplay` + * @n_formats: return location for the number of formats + * + * Returns the dma-buf formats that are supported for + * this display. + * + * Returns: (transfer none): an array of `GdkDmabufFormat` structs. + * The length of the array is returned in @n_formats + * + * Since: 4.14 + */ +const GdkDmabufFormat * +gdk_display_get_dmabuf_formats (GdkDisplay *display, + gsize *n_formats) +{ + gdk_display_prepare_gl (display, NULL); + + *n_formats = display->egl_dmabuf_n_formats; + return display->egl_dmabuf_formats; +} + GdkDebugFlags gdk_display_get_debug_flags (GdkDisplay *display) { diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h index eb559b17b2..609bfbd759 100644 --- a/gdk/gdkdisplay.h +++ b/gdk/gdkdisplay.h @@ -134,6 +134,17 @@ gboolean gdk_display_get_setting (GdkDisplay *display, const char *name, GValue *value); +typedef struct +{ + uint32_t fourcc; + uint64_t modifier; +} GdkDmabufFormat; + +GDK_AVAILABLE_IN_4_14 +const GdkDmabufFormat * + gdk_display_get_dmabuf_formats (GdkDisplay *display, + gsize *n_formats); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref) G_END_DECLS diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 9e829f617f..df15dc11bd 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -113,6 +113,9 @@ struct _GdkDisplay guint have_egl_buffer_age : 1; guint have_egl_no_config_context : 1; guint have_egl_pixel_format_float : 1; + + GdkDmabufFormat *egl_dmabuf_formats; + gsize egl_dmabuf_n_formats; }; struct _GdkDisplayClass