From: Varad Gautam <varad.gau...@collabora.com> mesa's freedreno driver supports importing dmabufs with format DRM_FORMAT_NV12 and DRM_FORMAT_MOD_SAMSUNG_64_32_TILE modifier. demonstrate weston modifier advertising and import path using this combination when run with --import-format=NV12.
Signed-off-by: Varad Gautam <varad.gau...@collabora.com> --- clients/simple-dmabuf-drm.c | 157 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 32 deletions(-) diff --git a/clients/simple-dmabuf-drm.c b/clients/simple-dmabuf-drm.c index 7cf0208..9205138 100644 --- a/clients/simple-dmabuf-drm.c +++ b/clients/simple-dmabuf-drm.c @@ -61,7 +61,10 @@ struct display { struct zwp_fullscreen_shell_v1 *fshell; struct zwp_linux_dmabuf_v1 *dmabuf; int xrgb8888_format_found; + int nv12_format_found; + int nv12_modifier_found; int req_dmabuf_immediate; + int req_dmabuf_modifiers; }; struct drm_device { @@ -98,6 +101,7 @@ struct buffer { int height; int bpp; unsigned long stride; + int format; }; #define NUM_BUFFERS 3 @@ -243,12 +247,13 @@ fill_content(struct buffer *my_buf) { int x = 0, y = 0; uint32_t *pix; + int scale_w = my_buf->format == DRM_FORMAT_NV12 ? 4 : 1; assert(my_buf->mmap); for (y = 0; y < my_buf->height; y++) { pix = (uint32_t *)(my_buf->mmap + y * my_buf->stride); - for (x = 0; x < my_buf->width; x++) { + for (x = 0; x < my_buf->width / scale_w; x++) { *pix++ = (0xff << 24) | ((x % 256) << 16) | ((y % 256) << 8) | 0xf0; } @@ -382,10 +387,10 @@ static const struct zwp_linux_buffer_params_v1_listener params_listener = { static int create_dmabuf_buffer(struct display *display, struct buffer *buffer, - int width, int height) + int width, int height, int format) { struct zwp_linux_buffer_params_v1 *params; - uint64_t modifier; + uint64_t modifier = 0; uint32_t flags; struct drm_device *drm_dev; @@ -396,8 +401,18 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer, drm_dev = buffer->dev; buffer->width = width; - buffer->height = height; - buffer->bpp = 32; /* hardcoded XRGB8888 format */ + switch (format) { + case DRM_FORMAT_NV12: + /* adjust height for allocation of NV12 Y and UV planes */ + buffer->height = height * 3 / 2; + buffer->bpp = 8; + modifier = DRM_FORMAT_MOD_SAMSUNG_64_32_TILE; + break; + default: + buffer->height = height; + buffer->bpp = 32; + } + buffer->format = format; if (!drm_dev->alloc_bo(buffer)) { fprintf(stderr, "alloc_bo failed\n"); @@ -420,10 +435,13 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer, goto error2; } - /* We now have a dmabuf! It should contain 2x2 tiles (i.e. each tile - * is 256x256) of misc colours, and be mappable, either as ARGB8888, or - * XRGB8888. */ - modifier = 0; + /* We now have a dmabuf! For format XRGB8888, it should contain 2x2 + * tiles (i.e. each tile is 256x256) of misc colours, and be mappable, + * either as ARGB8888, or XRGB8888. For format NV12, it should contain + * the Y and UV components, and needs to be re-adjusted for passing the + * correct height to the compositor. + */ + buffer->height = height; flags = 0; params = zwp_linux_dmabuf_v1_create_params(display->dmabuf); @@ -434,12 +452,23 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer, buffer->stride, modifier >> 32, modifier & 0xffffffff); + + if (format == DRM_FORMAT_NV12) { + /* add the second plane params */ + zwp_linux_buffer_params_v1_add(params, + buffer->dmabuf_fd, + 1, + buffer->width * buffer->height, + buffer->stride, + modifier >> 32, + modifier & 0xffffffff); + } zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, buffer); if (display->req_dmabuf_immediate) { buffer->buffer = zwp_linux_buffer_params_v1_create_immed(params, buffer->width, buffer->height, - DRM_FORMAT_XRGB8888, + format, flags); wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); } @@ -447,7 +476,7 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer, zwp_linux_buffer_params_v1_create(params, buffer->width, buffer->height, - DRM_FORMAT_XRGB8888, + format, flags); return 0; @@ -496,7 +525,7 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { }; static struct window * -create_window(struct display *display, int width, int height) +create_window(struct display *display, int width, int height, int format) { struct window *window; int i; @@ -545,7 +574,7 @@ create_window(struct display *display, int width, int height) for (i = 0; i < NUM_BUFFERS; ++i) { ret = create_dmabuf_buffer(display, &window->buffers[i], - width, height); + width, height, format); if (ret < 0) return NULL; @@ -632,7 +661,11 @@ static void dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) { - /* XXX: do something useful with modifiers */ + struct display *d = data; + uint64_t modifier = ((uint64_t) modifier_hi << 32) | modifier_lo; + + if (modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) + d->nv12_modifier_found = 1; } static void @@ -640,8 +673,15 @@ dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t { struct display *d = data; - if (format == DRM_FORMAT_XRGB8888) + switch (format) { + case DRM_FORMAT_XRGB8888: d->xrgb8888_format_found = 1; + break; + case DRM_FORMAT_NV12: + d->nv12_format_found = 1; + default: + break; + } } static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { @@ -677,9 +717,16 @@ registry_handle_global(void *data, struct wl_registry *registry, d->fshell = wl_registry_bind(registry, id, &zwp_fullscreen_shell_v1_interface, 1); } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) { + int ver; + if (d->req_dmabuf_modifiers) + ver = 3; + else if (d->req_dmabuf_immediate) + ver = 2; + else + ver = 1; d->dmabuf = wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, - d->req_dmabuf_immediate ? 2 : 1); + ver); zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener, d); } } @@ -696,7 +743,7 @@ static const struct wl_registry_listener registry_listener = { }; static struct display * -create_display(int is_immediate) +create_display(int is_immediate, int format) { struct display *display; @@ -708,9 +755,8 @@ create_display(int is_immediate) display->display = wl_display_connect(NULL); assert(display->display); - /* XXX: fake, because the compositor does not yet advertise anything */ - display->xrgb8888_format_found = 1; display->req_dmabuf_immediate = is_immediate; + display->req_dmabuf_modifiers = (format == DRM_FORMAT_NV12); display->registry = wl_display_get_registry(display->display); wl_registry_add_listener(display->registry, @@ -723,8 +769,10 @@ create_display(int is_immediate) wl_display_roundtrip(display->display); - if (!display->xrgb8888_format_found) { - fprintf(stderr, "DRM_FORMAT_XRGB8888 not available\n"); + if ((format == DRM_FORMAT_XRGB8888 && !display->xrgb8888_format_found) || + (format == DRM_FORMAT_NV12 && (!display->nv12_format_found || + !display->nv12_modifier_found))) { + fprintf(stderr, "requested format is not available\n"); exit(1); } @@ -758,6 +806,43 @@ signal_int(int signum) running = 0; } +static void +print_usage_and_exit(void) +{ + printf("usage flags:\n" + "\t'--import-immediate=<>'\n\t\t0 to import dmabuf via roundtrip," + "\n\t\t1 to enable import without roundtrip\n" + "\t'--import-format=<>'\n\t\tXRGB to import dmabuf as XRGB8888," + "\n\t\tNV12 to import as multi plane NV12 with tiling modifier\n"); + exit(0); +} + +static int +is_import_mode_immediate(const char* c) +{ + if (!strcmp(c, "1")) + return 1; + else if (!strcmp(c, "0")) + return 0; + else + print_usage_and_exit(); + + return 0; +} + +static int +parse_import_format(const char* c) +{ + if (!strcmp(c, "NV12")) + return DRM_FORMAT_NV12; + else if (!strcmp(c, "XRGB")) + return DRM_FORMAT_XRGB8888; + else + print_usage_and_exit(); + + return 0; +} + int main(int argc, char **argv) { @@ -765,22 +850,30 @@ main(int argc, char **argv) struct display *display; struct window *window; int is_immediate = 0; - int ret = 0; + int import_format = DRM_FORMAT_XRGB8888; + int ret = 0, i = 0; if (argc > 1) { - if (!strcmp(argv[1], "immed")) { - is_immediate = 1; - } - else { - fprintf(stderr, "usage:\n\tsimple-dmabuf-intel [options]\n" - "available options:\n\timmed: avoid dmabuf " - "creation roundtrip and import immediately\n"); - return 1; + static const char import_mode[] = "--import-immediate="; + static const char format[] = "--import-format="; + for (i = 1; i < argc; i++) { + if (!strncmp(argv[i], import_mode, + sizeof(import_mode) - 1)) { + is_immediate = is_import_mode_immediate(argv[i] + + sizeof(import_mode) - 1); + } + else if (!strncmp(argv[i], format, sizeof(format) - 1)) { + import_format = parse_import_format(argv[i] + + sizeof(format) - 1); + } + else { + print_usage_and_exit(); + } } } - display = create_display(is_immediate); - window = create_window(display, 250, 250); + display = create_display(is_immediate, import_format); + window = create_window(display, 256, 256, import_format); if (!window) return 1; -- 2.6.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel