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);