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, &params_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

Reply via email to