diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index 4ad7acf27..0fd1aee6c 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -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) +shm_format_to_string (MetaDrmFormatBuf *format_buf, + 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]); + } } }