From de2a4ebc3cfccc1cb3ddea08da2d64070afba732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Sun, 10 Nov 2024 13:45:23 +0100 Subject: [PATCH] clients: Let simple-shm create buffers of requested RGB format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a temporary solution to easily test wl_shm support for different RGB formats. I think it would be better to have a dedicated client to test all the supported RGB and YUV formats for the wl_shm, dma-buf import and legacy EGL protocols. Signed-off-by: Loïc Molinari --- clients/simple-shm.c | 300 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 284 insertions(+), 16 deletions(-) diff --git a/clients/simple-shm.c b/clients/simple-shm.c index cd4e991d8..a7cde8ef4 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -42,8 +43,18 @@ #include #include "xdg-shell-client-protocol.h" +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } } + #define MAX_BUFFER_ALLOC 2 +struct format { + uint32_t code; + const char *string; + int bpp; + uint64_t color[4]; +}; + struct display { struct wl_display *display; struct wl_registry *registry; @@ -52,7 +63,9 @@ struct display { struct wl_seat *seat; struct wl_keyboard *keyboard; struct wl_shm *shm; - bool has_xrgb; + const struct format *format; + bool paint_format; + bool has_format; }; struct buffer { @@ -81,6 +94,68 @@ struct window { bool needs_update_buffer; }; +static const struct format shm_formats[] = { + /* 8 bpp formats */ + FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ), + + /* 16 bpp formats */ + FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ), + FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ), + FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ), + FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ), + FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ), + FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ), + FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ), + FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ), + FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ), + FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ), + FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ), + FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ), + FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ), + FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ), + FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ), + FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ), + FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ), + FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ), + FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ), + FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ), + FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ), + + /* 24 bpp formats */ + FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ), + FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ), + + /* 32 bpp formats */ + FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ), + FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ), + FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ), + FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ), + FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ), + FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ), + FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ), + FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ), + FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ), + FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ), + FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ), + FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ), + FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ), + FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ), + FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ), + FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ), + FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ), + FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ), + + /* 64 bpp formats */ + FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ), + FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ), + FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ), + FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ), + FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ), + FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ), + FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ), + FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ), +}; + static int running = 1; static void @@ -151,7 +226,8 @@ static const struct wl_buffer_listener buffer_listener = { }; static int -create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format) +create_shm_buffer(struct window *window, struct buffer *buffer, + const struct format *format) { struct wl_shm_pool *pool; int fd, size, stride; @@ -161,7 +237,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format) width = window->width; height = window->height; - stride = width * 4; + stride = width * (format->bpp / 8); size = stride * height; display = window->display; @@ -182,7 +258,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format) pool = wl_shm_create_pool(display->shm, fd, size); buffer->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, - stride, format); + stride, format->code); wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); wl_shm_pool_destroy(pool); close(fd); @@ -416,14 +492,16 @@ window_next_buffer(struct window *window) return NULL; if (!buffer->buffer) { - ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888); + ret = create_shm_buffer(window, buffer, + window->display->format); if (ret < 0) return NULL; /* paint the padding */ memset(buffer->shm_data, 0xff, - window->width * window->height * 4); + window->width * window->height * + (window->display->format->bpp / 8)); } return buffer; @@ -475,6 +553,122 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time) } } +static void +paint_format(void *image, const struct format *format, int width, int height) +{ + uint64_t *img64 = (uint64_t*) image; + uint32_t *img32 = (uint32_t*) image; + uint16_t *img16 = (uint16_t*) image; + uint8_t *img8 = (uint8_t*) image; + uint64_t color; + int i, j; + +#define GET_COLOR(y) \ + (y < (1 * (height / 4))) ? format->color[0] : \ + (y < (2 * (height / 4))) ? format->color[1] : \ + (y < (3 * (height / 4))) ? format->color[2] : \ + format->color[3] + + switch (format->code) { + case WL_SHM_FORMAT_R8: + for (i = 0; i < height; i++) { + color = GET_COLOR(i); + for (j = 0; j < width; j++) + img8[i * width + j] = color; + } + break; + + case WL_SHM_FORMAT_R16: + case WL_SHM_FORMAT_GR88: + case WL_SHM_FORMAT_RG88: + case WL_SHM_FORMAT_RGB565: + case WL_SHM_FORMAT_BGR565: + case WL_SHM_FORMAT_XRGB4444: + case WL_SHM_FORMAT_ARGB4444: + case WL_SHM_FORMAT_XBGR4444: + case WL_SHM_FORMAT_ABGR4444: + case WL_SHM_FORMAT_RGBX4444: + case WL_SHM_FORMAT_RGBA4444: + case WL_SHM_FORMAT_BGRX4444: + case WL_SHM_FORMAT_BGRA4444: + case WL_SHM_FORMAT_XRGB1555: + case WL_SHM_FORMAT_ARGB1555: + case WL_SHM_FORMAT_XBGR1555: + case WL_SHM_FORMAT_ABGR1555: + case WL_SHM_FORMAT_RGBX5551: + case WL_SHM_FORMAT_RGBA5551: + case WL_SHM_FORMAT_BGRX5551: + case WL_SHM_FORMAT_BGRA5551: + for (i = 0; i < height; i++) { + color = GET_COLOR(i); + for (j = 0; j < width; j++) + img16[i * width + j] = color; + } + break; + + case WL_SHM_FORMAT_RGB888: + case WL_SHM_FORMAT_BGR888: + for (i = 0; i < height; i++) { + color = GET_COLOR(i); + for (j = 0; j < width; j++) { + img8[(i * width + j) * 3 + 0] = + (color >> 16) & 0xff; + img8[(i * width + j) * 3 + 1] = + (color >> 8) & 0xff; + img8[(i * width + j) * 3 + 2] = + (color >> 0) & 0xff; + } + } + break; + + case WL_SHM_FORMAT_GR1616: + case WL_SHM_FORMAT_RG1616: + case WL_SHM_FORMAT_XRGB8888: + case WL_SHM_FORMAT_ARGB8888: + case WL_SHM_FORMAT_XBGR8888: + case WL_SHM_FORMAT_ABGR8888: + case WL_SHM_FORMAT_RGBX8888: + case WL_SHM_FORMAT_RGBA8888: + case WL_SHM_FORMAT_BGRX8888: + case WL_SHM_FORMAT_BGRA8888: + case WL_SHM_FORMAT_XRGB2101010: + case WL_SHM_FORMAT_ARGB2101010: + case WL_SHM_FORMAT_XBGR2101010: + case WL_SHM_FORMAT_ABGR2101010: + case WL_SHM_FORMAT_RGBX1010102: + case WL_SHM_FORMAT_RGBA1010102: + case WL_SHM_FORMAT_BGRX1010102: + case WL_SHM_FORMAT_BGRA1010102: + for (i = 0; i < height; i++) { + color = GET_COLOR(i); + for (j = 0; j < width; j++) + img32[i * width + j] = color; + } + break; + + case WL_SHM_FORMAT_XRGB16161616: + case WL_SHM_FORMAT_ARGB16161616: + case WL_SHM_FORMAT_XBGR16161616: + case WL_SHM_FORMAT_ABGR16161616: + case WL_SHM_FORMAT_XRGB16161616F: + case WL_SHM_FORMAT_ARGB16161616F: + case WL_SHM_FORMAT_XBGR16161616F: + case WL_SHM_FORMAT_ABGR16161616F: + for (i = 0; i < height; i++) { + color = GET_COLOR(i); + for (j = 0; j < width; j++) + img64[i * width + j] = color; + } + break; + + default: + assert(0); + break; + }; + +#undef GET_COLOR +} + static const struct wl_callback_listener frame_listener; static void @@ -493,7 +687,12 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) abort(); } - paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + if (window->display->paint_format) + paint_format(buffer->shm_data, window->display->format, + window->width, window->height); + else + paint_pixels(buffer->shm_data, 20, window->width, + window->height, time); wl_surface_attach(window->surface, buffer->buffer, 0, 0); wl_surface_damage(window->surface, @@ -517,8 +716,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { struct display *d = data; - if (format == WL_SHM_FORMAT_XRGB8888) - d->has_xrgb = true; + if (format == d->format->code) + d->has_format = true; } struct wl_shm_listener shm_listener = { @@ -572,7 +771,7 @@ static const struct wl_registry_listener registry_listener = { }; static struct display * -create_display(void) +create_display(const struct format *format, bool paint_format) { struct display *display; @@ -584,7 +783,9 @@ create_display(void) display->display = wl_display_connect(NULL); assert(display->display); - display->has_xrgb = false; + display->format = format; + display->paint_format = paint_format; + display->has_format= false; display->registry = wl_display_get_registry(display->display); wl_registry_add_listener(display->registry, ®istry_listener, display); @@ -636,8 +837,9 @@ create_display(void) * technique. */ - if (!display->has_xrgb) { - fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n"); + if (!display->has_format) { + fprintf(stderr, "Format '%s' not supported by compositor.\n", + format->string); exit(1); } @@ -668,16 +870,82 @@ signal_int(int signum) running = 0; } +static void +usage(const char *program) +{ + fprintf(stdout, + "Usage: %s [OPTIONS]\n" + "\n" + "Draw pixels into shared memory buffers using wl_shm\n" + "\n" + "Options:\n" + " -h, --help Show this help\n" + " -F, --format Test format (see list below)\n" + "\n" + "RGB formats:\n" + " - 8 bpp: r8.\n" + "\n" + " - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n" + " abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n" + " argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n" + " bgra5551.\n" + "\n" + " - 24 bpp: rgb888, bgr888.\n" + "\n" + " - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n" + " rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n" + " abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n" + "\n" + " - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n" + " xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n", + program); +} + int main(int argc, char **argv) { struct sigaction sigint; struct display *display; struct window *window; - int ret = 0; + const struct format *format = NULL; + bool paint_format = false; + const char *value; + int ret = 0, i, j; - display = create_display(); - window = create_window(display, 250, 250); + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h") || + !strcmp(argv[i], "--help")) { + usage(argv[0]); + return 0; + } else if (!strcmp(argv[i], "-F") || + !strcmp(argv[i], "--format")) { + value = ++i == argc ? "" : argv[i]; + for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) { + if (!strcasecmp(shm_formats[j].string, value)) { + format = &shm_formats[j]; + paint_format = true; + break; + } + } + if (!format) { + fprintf(stderr, "Format '%s' not supported by " + "client.\n", value); + return 1; + } + } else { + fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]); + return 1; + } + } + + if (!format) + for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++) + if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888) + format = &shm_formats[i]; + assert(format); + + display = create_display(format, paint_format); + window = create_window(display, 256, 256); if (!window) return 1;