From 8a7f1e2bc0580394a0c7a6c349e7264e695a0343 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Mon, 26 Jul 2021 22:29:20 -0400 Subject: [PATCH] pixman-renderer: track Pixman formats in pixel format table Adds a Pixman format field to the pixel format table, and adjusts the shm format handling code in the Pixman renderer to use this table. Pixman formats have been registered only for specific 565, 8888, and 2101010 layouts, as these have corresponding DRM format codes and are commonly used. Signed-off-by: Manuel Stoeckl --- libweston/pixel-formats.c | 67 +++++++++++++++++++++++++++++++++++++ libweston/pixel-formats.h | 25 ++++++++++++++ libweston/pixman-renderer.c | 42 +++++++++++++---------- 3 files changed, 116 insertions(+), 18 deletions(-) diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c index 9c19a550..9064cb66 100644 --- a/libweston/pixel-formats.c +++ b/libweston/pixel-formats.c @@ -65,6 +65,8 @@ .bits.a = a_, \ .component_type = PIXEL_COMPONENT_TYPE_FIXED +#define PIXMAN_FMT(fmt) .pixman_format = (PIXMAN_ ## fmt) + #include "shared/weston-egl-ext.h" /** @@ -171,6 +173,7 @@ static const struct pixel_format_info pixel_format_table[] = { # if __BYTE_ORDER == __LITTLE_ENDIAN GL_FORMAT(GL_RGB), GL_TYPE(GL_UNSIGNED_SHORT_5_6_5), + PIXMAN_FMT(r5g6b5), #endif }, { @@ -194,6 +197,11 @@ static const struct pixel_format_info pixel_format_table[] = { .bpp = 32, GL_FORMAT(GL_BGRA_EXT), GL_TYPE(GL_UNSIGNED_BYTE), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(x8r8g8b8), +#else + PIXMAN_FMT(b8g8r8x8), +#endif }, { DRM_FORMAT(ARGB8888), @@ -203,12 +211,22 @@ static const struct pixel_format_info pixel_format_table[] = { .bpp = 32, GL_FORMAT(GL_BGRA_EXT), GL_TYPE(GL_UNSIGNED_BYTE), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(a8r8g8b8), +#else + PIXMAN_FMT(b8g8r8a8), +#endif }, { DRM_FORMAT(XBGR8888), BITS_RGBA_FIXED(8, 8, 8, 0), GL_FORMAT(GL_RGBA), GL_TYPE(GL_UNSIGNED_BYTE), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(x8b8g8r8), +#else + PIXMAN_FMT(r8g8b8x8), +#endif }, { DRM_FORMAT(ABGR8888), @@ -216,35 +234,66 @@ static const struct pixel_format_info pixel_format_table[] = { .opaque_substitute = DRM_FORMAT_XBGR8888, GL_FORMAT(GL_RGBA), GL_TYPE(GL_UNSIGNED_BYTE), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(a8b8g8r8), +#else + PIXMAN_FMT(r8g8b8a8), +#endif }, { DRM_FORMAT(RGBX8888), BITS_RGBA_FIXED(8, 8, 8, 0), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(r8g8b8x8), +#else + PIXMAN_FMT(x8b8g8r8), +#endif }, { DRM_FORMAT(RGBA8888), BITS_RGBA_FIXED(8, 8, 8, 8), .opaque_substitute = DRM_FORMAT_RGBX8888, +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(r8g8b8a8), +#else + PIXMAN_FMT(a8b8g8r8), +#endif }, { DRM_FORMAT(BGRX8888), BITS_RGBA_FIXED(8, 8, 8, 0), +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(b8g8r8x8), +#else + PIXMAN_FMT(x8r8g8b8), +#endif }, { DRM_FORMAT(BGRA8888), BITS_RGBA_FIXED(8, 8, 8, 8), .opaque_substitute = DRM_FORMAT_BGRX8888, +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(b8g8r8a8), +#else + PIXMAN_FMT(a8r8g8b8), +#endif }, { DRM_FORMAT(XRGB2101010), BITS_RGBA_FIXED(10, 10, 10, 0), .depth = 30, .bpp = 32, +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(x2r10g10b10), +#endif }, { DRM_FORMAT(ARGB2101010), BITS_RGBA_FIXED(10, 10, 10, 2), .opaque_substitute = DRM_FORMAT_XRGB2101010, +#if __BYTE_ORDER == __LITTLE_ENDIAN + PIXMAN_FMT(a2r10g10b10), +#endif }, { DRM_FORMAT(XBGR2101010), @@ -252,6 +301,7 @@ static const struct pixel_format_info pixel_format_table[] = { # if __BYTE_ORDER == __LITTLE_ENDIAN GL_FORMAT(GL_RGBA), GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT), + PIXMAN_FMT(x2b10g10r10), #endif }, { @@ -261,6 +311,7 @@ static const struct pixel_format_info pixel_format_table[] = { # if __BYTE_ORDER == __LITTLE_ENDIAN GL_FORMAT(GL_RGBA), GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT), + PIXMAN_FMT(a2b10g10r10), #endif }, { @@ -447,6 +498,22 @@ pixel_format_get_info(uint32_t format) return NULL; } +WL_EXPORT const struct pixel_format_info * +pixel_format_get_info_by_index(unsigned int index) +{ + if (index >= ARRAY_LENGTH(pixel_format_table)) + return NULL; + + return &pixel_format_table[index]; +} + +WL_EXPORT unsigned int +pixel_format_get_info_count(void) +{ + return ARRAY_LENGTH(pixel_format_table); +} + + WL_EXPORT const struct pixel_format_info * pixel_format_get_info_by_drm_name(const char *drm_format_name) { diff --git a/libweston/pixel-formats.h b/libweston/pixel-formats.h index d96bcfbe..0b1a5f58 100644 --- a/libweston/pixel-formats.h +++ b/libweston/pixel-formats.h @@ -26,6 +26,7 @@ #include #include +#include /** * Contains information about pixel formats, mapping format codes from @@ -70,6 +71,9 @@ struct pixel_format_info { /** GL data type, if data can be natively/directly uploaded. */ int gl_type; + /** Pixman data type, if it agrees exactly with the wl_shm format */ + pixman_format_code_t pixman_format; + /** If set, this format can be used with the legacy drmModeAddFB() * function (not AddFB2), using this and the bpp member. */ int depth; @@ -142,6 +146,27 @@ pixel_format_get_info(uint32_t format); const struct pixel_format_info * pixel_format_get_info_shm(uint32_t format); +/** + * Get pixel format information by table index + * + * Given a 0-based index in the format table, return the corresponding + * DRM pixel format info structure. + * + * @param index Index of the pixel format in the table + * @returns A pixel format structure (must not be freed), or NULL if the + * index is out of range. + */ +const struct pixel_format_info * +pixel_format_get_info_by_index(unsigned int index); + +/** + * Return the size of the pixel format table + * + * @returns The number of entries in the pixel format table + */ +unsigned int +pixel_format_get_info_count(void); + /** * Get pixel format information for a named DRM format * diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index ebc0fa79..754adce2 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -34,6 +34,7 @@ #include "pixman-renderer.h" #include "color.h" +#include "pixel-formats.h" #include "shared/helpers.h" #include @@ -623,7 +624,7 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { struct pixman_surface_state *ps = get_surface_state(es); struct wl_shm_buffer *shm_buffer; - pixman_format_code_t pixman_format; + const struct pixel_format_info *pixel_info; weston_buffer_reference(&ps->buffer_ref, buffer); weston_buffer_release_reference(&ps->buffer_release_ref, @@ -651,20 +652,8 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) return; } - switch (wl_shm_buffer_get_format(shm_buffer)) { - case WL_SHM_FORMAT_XRGB8888: - pixman_format = PIXMAN_x8r8g8b8; - es->is_opaque = true; - break; - case WL_SHM_FORMAT_ARGB8888: - pixman_format = PIXMAN_a8r8g8b8; - es->is_opaque = false; - break; - case WL_SHM_FORMAT_RGB565: - pixman_format = PIXMAN_r5g6b5; - es->is_opaque = true; - break; - default: + pixel_info = pixel_format_get_info_shm(wl_shm_buffer_get_format(shm_buffer)); + if (!pixel_info || !pixman_format_supported_source(pixel_info->pixman_format)) { weston_log("Unsupported SHM buffer format 0x%x\n", wl_shm_buffer_get_format(shm_buffer)); weston_buffer_reference(&ps->buffer_ref, NULL); @@ -672,14 +661,15 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) weston_buffer_send_server_error(buffer, "disconnecting due to unhandled buffer type"); return; - break; } + es->is_opaque = pixel_format_is_opaque(pixel_info); + buffer->shm_buffer = shm_buffer; buffer->width = wl_shm_buffer_get_width(shm_buffer); buffer->height = wl_shm_buffer_get_height(shm_buffer); - ps->image = pixman_image_create_bits(pixman_format, + ps->image = pixman_image_create_bits(pixel_info->pixman_format, buffer->width, buffer->height, wl_shm_buffer_get_data(shm_buffer), wl_shm_buffer_get_stride(shm_buffer)); @@ -864,6 +854,8 @@ WL_EXPORT int pixman_renderer_init(struct weston_compositor *ec) { struct pixman_renderer *renderer; + const struct pixel_format_info *pixel_info, *info_argb8888, *info_xrgb8888; + unsigned int i, num_formats; renderer = zalloc(sizeof *renderer); if (renderer == NULL) @@ -889,7 +881,21 @@ pixman_renderer_init(struct weston_compositor *ec) weston_compositor_add_debug_binding(ec, KEY_R, debug_binding, ec); - wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565); + info_argb8888 = pixel_format_get_info_shm(WL_SHM_FORMAT_ARGB8888); + info_xrgb8888 = pixel_format_get_info_shm(WL_SHM_FORMAT_XRGB8888); + + num_formats = pixel_format_get_info_count(); + for (i = 0; i < num_formats; i++) { + pixel_info = pixel_format_get_info_by_index(i); + if (!pixman_format_supported_source(pixel_info->pixman_format)) + continue; + + /* skip formats which libwayland registers by default */ + if (pixel_info == info_argb8888 || pixel_info == info_xrgb8888) + continue; + + wl_display_add_shm_format(ec->wl_display, pixel_info->format); + } wl_signal_init(&renderer->destroy_signal);