wayland-buffer: Use MetaFormatInfo to find supported formats

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3280>
This commit is contained in:
Sebastian Wick 2023-08-08 21:23:53 +02:00 committed by Marge Bot
parent dbdc821ca7
commit 97c1d19017

View File

@ -56,6 +56,8 @@
#include "meta/util.h"
#include "wayland/meta-wayland-dma-buf.h"
#include "wayland/meta-wayland-private.h"
#include "common/meta-cogl-drm-formats.h"
#include "compositor/meta-multi-texture-format-private.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-drm-buffer-gbm.h"
@ -64,6 +66,8 @@
#include "backends/native/meta-renderer-native.h"
#endif
#define META_WAYLAND_SHM_MAX_PLANES 4
enum
{
RESOURCE_DESTROYED,
@ -75,6 +79,9 @@ guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (MetaWaylandBuffer, meta_wayland_buffer, G_TYPE_OBJECT);
MetaFormatInfo supported_shm_formats[G_N_ELEMENTS (meta_format_info)];
size_t n_supported_shm_formats = 0;
static void
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
void *data)
@ -205,123 +212,43 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
return FALSE;
}
static gboolean
shm_format_to_cogl_pixel_format (enum wl_shm_format shm_format,
CoglPixelFormat *format_out)
static uint32_t
shm_to_drm_format (enum wl_shm_format format)
{
CoglPixelFormat format;
if (format == WL_SHM_FORMAT_ARGB8888)
return DRM_FORMAT_ARGB8888;
if (format == WL_SHM_FORMAT_XRGB8888)
return DRM_FORMAT_XRGB8888;
switch (shm_format)
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_XRGB_8888;
break;
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case WL_SHM_FORMAT_XBGR8888:
format = COGL_PIXEL_FORMAT_XBGR_8888;
case WL_SHM_FORMAT_ABGR8888:
format = COGL_PIXEL_FORMAT_ABGR_8888_PRE;
break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_RGB565:
format = COGL_PIXEL_FORMAT_RGB_565;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRX_8888;
break;
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
break;
case WL_SHM_FORMAT_XBGR8888:
format = COGL_PIXEL_FORMAT_RGBX_8888;
break;
case WL_SHM_FORMAT_ABGR8888:
format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB2101010:
format = COGL_PIXEL_FORMAT_XRGB_2101010;
break;
case WL_SHM_FORMAT_ARGB2101010:
format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
break;
case WL_SHM_FORMAT_XBGR2101010:
format = COGL_PIXEL_FORMAT_XBGR_2101010;
break;
case WL_SHM_FORMAT_ABGR2101010:
format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE;
break;
case WL_SHM_FORMAT_XRGB16161616F:
format = COGL_PIXEL_FORMAT_BGRX_FP_16161616;
break;
case WL_SHM_FORMAT_ARGB16161616F:
format = COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE;
break;
case WL_SHM_FORMAT_XBGR16161616F:
format = COGL_PIXEL_FORMAT_RGBX_FP_16161616;
break;
case WL_SHM_FORMAT_ABGR16161616F:
format = COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE;
break;
#endif
default:
return FALSE;
}
if (format_out)
*format_out = format;
return TRUE;
}
static gboolean
shm_buffer_get_cogl_pixel_format (MetaWaylandBuffer *buffer,
struct wl_shm_buffer *shm_buffer,
CoglPixelFormat *format_out)
{
MetaContext *context =
meta_wayland_compositor_get_context (buffer->compositor);
MetaBackend *backend = meta_context_get_backend (context);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
CoglPixelFormat cogl_format;
if (!shm_format_to_cogl_pixel_format (wl_shm_buffer_get_format (shm_buffer),
&cogl_format))
return FALSE;
if (!cogl_context_format_supports_upload (cogl_context, cogl_format))
return FALSE;
if (format_out)
*format_out = cogl_format;
return TRUE;
/* all other wayland shm formats are the same as the drm format */
return format;
}
static const char *
shm_format_to_string (MetaDrmFormatBuf *format_buf,
uint32_t shm_format)
enum wl_shm_format shm_format)
{
const char *result;
uint32_t drm_format;
switch (shm_format)
drm_format = shm_to_drm_format (shm_format);
return meta_drm_format_to_string (format_buf, drm_format);
}
static const MetaFormatInfo *
get_supported_shm_format_info (uint32_t shm_format)
{
size_t i;
for (i = 0; i < n_supported_shm_formats; i++)
{
case WL_SHM_FORMAT_ARGB8888:
result = "ARGB8888";
break;
case WL_SHM_FORMAT_XRGB8888:
result = "XRGB8888";
break;
default:
result = meta_drm_format_to_string (format_buf, shm_format);
break;
uint32_t drm_format;
drm_format = shm_to_drm_format (shm_format);
if (supported_shm_formats[i].drm_format == drm_format)
return &supported_shm_formats[i];
}
return result;
return NULL;
}
static gboolean
@ -340,23 +267,30 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
CoglBitmap *bitmap;
CoglTexture *new_cogl_tex;
MetaDrmFormatBuf format_buf;
uint32_t shm_format;
const MetaFormatInfo *format_info;
shm_buffer = wl_shm_buffer_get (buffer->resource);
stride = wl_shm_buffer_get_stride (shm_buffer);
width = wl_shm_buffer_get_width (shm_buffer);
height = wl_shm_buffer_get_height (shm_buffer);
if (!shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, &format))
shm_format = wl_shm_buffer_get_format (shm_buffer);
format_info = get_supported_shm_format_info (shm_format);
if (!format_info)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid shm pixel format");
return FALSE;
}
g_assert (format_info->multi_texture_format == META_MULTI_TEXTURE_FORMAT_SIMPLE);
format = format_info->cogl_format;
meta_topic (META_DEBUG_WAYLAND,
"[wl-shm] wl_buffer@%u wl_shm_format %s -> CoglPixelFormat %s",
wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)),
shm_format_to_string (&format_buf,
wl_shm_buffer_get_format (shm_buffer)),
shm_format_to_string (&format_buf, shm_format),
cogl_pixel_format_to_string (format));
if (*texture &&
@ -683,12 +617,20 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer,
gboolean set_texture_failed = FALSE;
CoglPixelFormat format;
CoglTexture *cogl_texture;
uint32_t shm_format;
const MetaFormatInfo *format_info;
n_rectangles = mtk_region_num_rectangles (region);
shm_buffer = wl_shm_buffer_get (buffer->resource);
shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, &format);
shm_format = wl_shm_buffer_get_format (shm_buffer);
format_info = get_supported_shm_format_info (shm_format);
g_assert (format_info != NULL);
g_assert (format_info->multi_texture_format == META_MULTI_TEXTURE_FORMAT_SIMPLE);
format = format_info->cogl_format;
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
cogl_texture = meta_multi_texture_get_plane (texture, 0);
@ -912,6 +854,35 @@ meta_wayland_buffer_class_init (MetaWaylandBufferClass *klass)
G_TYPE_NONE, 0);
}
static gboolean
context_supports_format (CoglContext *cogl_context,
const MetaFormatInfo *format_info)
{
const MetaMultiTextureFormatInfo *mt_format_info;
size_t i;
if (format_info->multi_texture_format == META_MULTI_TEXTURE_FORMAT_INVALID)
return FALSE;
if (format_info->multi_texture_format == META_MULTI_TEXTURE_FORMAT_SIMPLE)
{
return cogl_context_format_supports_upload (cogl_context,
format_info->cogl_format);
}
mt_format_info =
meta_multi_texture_format_get_info (format_info->multi_texture_format);
for (i = 0; i < mt_format_info->n_planes; i++)
{
if (!cogl_context_format_supports_upload (cogl_context,
mt_format_info->subformats[i]))
return FALSE;
}
return TRUE;
}
void
meta_wayland_init_shm (MetaWaylandCompositor *compositor)
{
@ -920,11 +891,13 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor)
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
int i;
static const enum wl_shm_format shm_formats[] = {
static const enum wl_shm_format possible_formats[] = {
WL_SHM_FORMAT_ARGB8888,
WL_SHM_FORMAT_XRGB8888,
WL_SHM_FORMAT_ABGR8888,
WL_SHM_FORMAT_XBGR8888,
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
WL_SHM_FORMAT_RGB565,
WL_SHM_FORMAT_ARGB2101010,
WL_SHM_FORMAT_XRGB2101010,
@ -934,22 +907,31 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor)
WL_SHM_FORMAT_XRGB16161616F,
WL_SHM_FORMAT_ABGR16161616F,
WL_SHM_FORMAT_XBGR16161616F,
#endif
};
int i;
wl_display_init_shm (compositor->wayland_display);
for (i = 0; i < G_N_ELEMENTS (shm_formats); i++)
n_supported_shm_formats = 0;
for (i = 0; i < G_N_ELEMENTS (possible_formats); i++)
{
CoglPixelFormat cogl_format;
const MetaFormatInfo *format_info;
uint32_t drm_format;
if (!shm_format_to_cogl_pixel_format (shm_formats[i], &cogl_format))
drm_format = shm_to_drm_format (possible_formats[i]);
format_info = meta_format_info_from_drm_format (drm_format);
g_assert (format_info);
if (!context_supports_format (cogl_context, format_info))
continue;
if (!cogl_context_format_supports_upload (cogl_context, cogl_format))
continue;
supported_shm_formats[n_supported_shm_formats++] = *format_info;
wl_display_add_shm_format (compositor->wayland_display, shm_formats[i]);
if (possible_formats[i] != WL_SHM_FORMAT_ARGB8888 &&
possible_formats[i] != WL_SHM_FORMAT_XRGB8888)
{
wl_display_add_shm_format (compositor->wayland_display,
possible_formats[i]);
}
}
}