wayland/dma-buf: Prepare format/modifier map up front

As the format table is setup up front, it doesn't change when this
experimental feature setting change. Make the settings documentation
reflect that.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
This commit is contained in:
Jonas Ådahl 2021-08-04 10:17:15 +02:00 committed by Marge Bot
parent 51308a9d78
commit 1978e93f28
2 changed files with 110 additions and 74 deletions

View File

@ -134,7 +134,7 @@
• “kms-modifiers” — makes mutter always advertise valid • “kms-modifiers” — makes mutter always advertise valid
buffer modifiers on Wayland. This is buffer modifiers on Wayland. This is
currently not the case when using the currently not the case when using the
i915 driver. Does not require a restart. i915 driver. Requires a restart.
• “rt-scheduler” — makes mutter request a low priority • “rt-scheduler” — makes mutter request a low priority
real-time scheduling. Requires a restart. real-time scheduling. Requires a restart.

View File

@ -66,9 +66,17 @@
#define META_WAYLAND_DMA_BUF_MAX_FDS 4 #define META_WAYLAND_DMA_BUF_MAX_FDS 4
typedef struct _MetaWaylandDmaBufFormat
{
uint32_t drm_format;
uint64_t drm_modifier;
} MetaWaylandDmaBufFormat;
struct _MetaWaylandDmaBufManager struct _MetaWaylandDmaBufManager
{ {
MetaWaylandCompositor *compositor; MetaWaylandCompositor *compositor;
GArray *formats;
}; };
struct _MetaWaylandDmaBufBuffer struct _MetaWaylandDmaBufBuffer
@ -650,70 +658,19 @@ should_send_modifiers (MetaBackend *backend)
} }
static void static void
send_modifiers (struct wl_resource *resource, send_modifiers (struct wl_resource *resource,
uint32_t format) MetaWaylandDmaBufFormat *format)
{ {
MetaBackend *backend = meta_get_backend (); zwp_linux_dmabuf_v1_send_format (resource, format->drm_format);
MetaEgl *egl = meta_backend_get_egl (backend);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
EGLint num_modifiers;
EGLuint64KHR *modifiers;
GError *error = NULL;
gboolean ret;
int i;
zwp_linux_dmabuf_v1_send_format (resource, format); if (wl_resource_get_version (resource) <
ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
/* The modifier event was only added in v3; v1 and v2 only have the format
* event. */
if (wl_resource_get_version (resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
return; return;
if (!should_send_modifiers (backend)) zwp_linux_dmabuf_v1_send_modifier (resource,
{ format->drm_format,
zwp_linux_dmabuf_v1_send_modifier (resource, format, format->drm_modifier >> 32,
DRM_FORMAT_MOD_INVALID >> 32, format->drm_modifier & 0xffffffff);
DRM_FORMAT_MOD_INVALID & 0xffffffff);
return;
}
/* First query the number of available modifiers, then allocate an array,
* then fill the array. */
ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format, 0, NULL,
NULL, &num_modifiers, NULL);
if (!ret)
return;
if (num_modifiers == 0)
{
zwp_linux_dmabuf_v1_send_modifier (resource, format,
DRM_FORMAT_MOD_INVALID >> 32,
DRM_FORMAT_MOD_INVALID & 0xffffffff);
return;
}
modifiers = g_new0 (uint64_t, num_modifiers);
ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format,
num_modifiers, modifiers, NULL,
&num_modifiers, &error);
if (!ret)
{
g_warning ("Failed to query modifiers for format 0x%" PRIu32 ": %s",
format, error ? error->message : "unknown error");
g_free (modifiers);
return;
}
for (i = 0; i < num_modifiers; i++)
{
zwp_linux_dmabuf_v1_send_modifier (resource, format,
modifiers[i] >> 32,
modifiers[i] & 0xffffffff);
}
g_free (modifiers);
} }
static void static void
@ -724,24 +681,100 @@ dma_buf_bind (struct wl_client *client,
{ {
MetaWaylandDmaBufManager *dma_buf_manager = user_data; MetaWaylandDmaBufManager *dma_buf_manager = user_data;
struct wl_resource *resource; struct wl_resource *resource;
unsigned int i;
resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface, resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface,
version, id); version, id);
wl_resource_set_implementation (resource, &dma_buf_implementation, wl_resource_set_implementation (resource, &dma_buf_implementation,
dma_buf_manager, NULL); dma_buf_manager, NULL);
send_modifiers (resource, DRM_FORMAT_ARGB8888);
send_modifiers (resource, DRM_FORMAT_ABGR8888);
send_modifiers (resource, DRM_FORMAT_XRGB8888); for (i = 0; i < dma_buf_manager->formats->len; i++)
send_modifiers (resource, DRM_FORMAT_XBGR8888); {
send_modifiers (resource, DRM_FORMAT_ARGB2101010); MetaWaylandDmaBufFormat *format =
send_modifiers (resource, DRM_FORMAT_ABGR2101010); &g_array_index (dma_buf_manager->formats,
send_modifiers (resource, DRM_FORMAT_XRGB2101010); MetaWaylandDmaBufFormat,
send_modifiers (resource, DRM_FORMAT_ABGR2101010); i);
send_modifiers (resource, DRM_FORMAT_RGB565);
send_modifiers (resource, DRM_FORMAT_ABGR16161616F); send_modifiers (resource, format);
send_modifiers (resource, DRM_FORMAT_XBGR16161616F); }
send_modifiers (resource, DRM_FORMAT_XRGB16161616F); }
send_modifiers (resource, DRM_FORMAT_ARGB16161616F);
static void
add_format (MetaWaylandDmaBufManager *dma_buf_manager,
EGLDisplay egl_display,
uint32_t drm_format)
{
MetaContext *context = dma_buf_manager->compositor->context;
MetaBackend *backend = meta_context_get_backend (context);
MetaEgl *egl = meta_backend_get_egl (backend);
EGLint num_modifiers;
g_autofree EGLuint64KHR *modifiers = NULL;
g_autoptr (GError) error = NULL;
int i;
MetaWaylandDmaBufFormat format;
if (!should_send_modifiers (backend))
goto add_fallback;
/* First query the number of available modifiers, then allocate an array,
* then fill the array. */
if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, drm_format, 0, NULL,
NULL, &num_modifiers, NULL))
goto add_fallback;
if (num_modifiers == 0)
goto add_fallback;
modifiers = g_new0 (uint64_t, num_modifiers);
if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, drm_format,
num_modifiers, modifiers, NULL,
&num_modifiers, &error))
{
g_warning ("Failed to query modifiers for format 0x%" PRIu32 ": %s",
drm_format, error ? error->message : "unknown error");
goto add_fallback;
}
for (i = 0; i < num_modifiers; i++)
{
format = (MetaWaylandDmaBufFormat) {
.drm_format = drm_format,
.drm_modifier = modifiers[i],
};
g_array_append_val (dma_buf_manager->formats, format);
}
return;
add_fallback:
format = (MetaWaylandDmaBufFormat) {
.drm_format = drm_format,
.drm_modifier = DRM_FORMAT_MOD_INVALID,
};
g_array_append_val (dma_buf_manager->formats, format);
}
static void
init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
EGLDisplay egl_display)
{
dma_buf_manager->formats = g_array_new (FALSE, FALSE,
sizeof (MetaWaylandDmaBufFormat));
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB8888);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR8888);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB8888);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR8888);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB2101010);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR2101010);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB2101010);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR2101010);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_RGB565);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR16161616F);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR16161616F);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB16161616F);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB16161616F);
} }
/** /**
@ -790,12 +823,15 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
dma_buf_manager->compositor = compositor; dma_buf_manager->compositor = compositor;
init_formats (dma_buf_manager, egl_display);
return g_steal_pointer (&dma_buf_manager); return g_steal_pointer (&dma_buf_manager);
} }
void void
meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager) meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager)
{ {
g_clear_pointer (&dma_buf_manager->formats, g_array_unref);
g_free (dma_buf_manager); g_free (dma_buf_manager);
} }