Add an example of tdm backend 31/278131/1
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 24 Feb 2022 06:01:35 +0000 (15:01 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:58:05 +0000 (14:58 +0900)
Change-Id: I836ba2b5b88d3799c7b095051e255779d653fa10

examples/meson.build
examples/tdm-backend.c [new file with mode: 0644]
meson.build
packaging/libds.spec

index a107a77..530cbdd 100644 (file)
@@ -1,15 +1,18 @@
-project('libds-samples', 'c',
-  version : '0.1',
-  default_options : ['warning_level=3'])
-
 common_deps = [
+  dep_libds,
   dependency('wayland-server', required: true),
-  dependency('libds', required: true),
 ]
 
 executable('wl-backend',
            'wl-backend.c',
            dependencies: common_deps,
+           install_dir: libds_bindir,
+           install : true)
+
+executable('tdm-backend',
+           'tdm-backend.c',
+           dependencies: common_deps,
+           install_dir: libds_bindir,
            install : true)
 
 executable('tinyds',
@@ -19,4 +22,5 @@ executable('tinyds',
              dependency('pixman-1', required: true),
              dependency('libdrm', required: true),
            ],
+           install_dir: libds_bindir,
            install : true)
diff --git a/examples/tdm-backend.c b/examples/tdm-backend.c
new file mode 100644 (file)
index 0000000..15f5711
--- /dev/null
@@ -0,0 +1,248 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <wayland-server.h>
+#include <libds/log.h>
+#include <libds/backend.h>
+#include <libds/output.h>
+#include <libds/allocator/tbm.h>
+#include <libds/backend/tdm.h>
+#include <libds/swapchain.h>
+#include <libds/compositor.h>
+
+#define WIDTH   1280
+#define HEIGHT  720
+
+struct server
+{
+    struct ds_backend *backend;
+    struct ds_output *output;
+    struct ds_allocator *allocator;
+    struct ds_swapchain *swapchain;
+    struct ds_buffer *front_buffer;
+
+    struct wl_display *display;
+    struct wl_event_source *stdin_source;
+
+    struct wl_listener new_output;
+    struct wl_listener output_destroy;
+    struct wl_listener output_frame;
+
+    int width, height;
+};
+
+struct server _server;
+
+static void init_server(struct server *server, struct wl_display *display);
+static void fini_server(struct server *server);
+static void output_handle_destroy(struct wl_listener *listener, void *data);
+static void output_handle_frame(struct wl_listener *listener, void *data);
+static void draw_output(struct server *server);
+static int stdin_dispatch(int fd, uint32_t mask, void *data);
+
+int
+main(void)
+{
+    struct server *server = &_server;
+    struct wl_display *display;
+
+    ds_log_init(DS_DBG, NULL);
+
+    display = wl_display_create();
+    assert(display);
+
+    server->width = WIDTH;
+    server->height = HEIGHT;
+
+    init_server(server, display);
+
+    ds_backend_start(server->backend);
+
+    draw_output(server);
+
+    struct wl_event_loop *loop = wl_display_get_event_loop(display);
+    server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
+            WL_EVENT_READABLE, stdin_dispatch, server);
+
+    wl_display_run(display);
+
+    fini_server(server);
+    wl_display_destroy(display);
+    return 0;
+}
+
+static void
+backend_handle_new_output(struct wl_listener *listener, void *data)
+{
+    struct server *server;
+    struct ds_output *output;
+
+    server = wl_container_of(listener, server, new_output);
+    output = data;
+    ds_inf("New output(%p)", output);
+
+
+    if (server->output)
+        return;
+
+    server->output = output;
+
+    server->output_destroy.notify = output_handle_destroy;
+    ds_output_add_destroy_listener(server->output,
+            &server->output_destroy);
+
+    server->output_frame.notify = output_handle_frame;
+    ds_output_add_frame_listener(server->output,
+            &server->output_frame);
+}
+
+static void
+init_server(struct server *server, struct wl_display *display)
+{
+    server->display = display;
+    server->front_buffer = NULL;
+
+    server->backend = ds_tdm_backend_create(display);
+    assert(server->backend);
+
+
+    server->new_output.notify = backend_handle_new_output;
+    ds_backend_add_new_output_listener(server->backend,
+            &server->new_output);
+
+    server->allocator = ds_tbm_allocator_create();
+    assert(server->allocator);
+
+    server->swapchain = ds_swapchain_create(server->allocator,
+            server->width, server->height, WL_SHM_FORMAT_XRGB8888);
+    assert(server->swapchain);
+}
+
+static void
+fini_server(struct server *server)
+{
+    wl_list_remove(&server->new_output.link);
+    wl_list_remove(&server->output_destroy.link);
+    wl_list_remove(&server->output_frame.link);
+    if (server->front_buffer)
+        ds_buffer_unlock(server->front_buffer);
+    ds_swapchain_destroy(server->swapchain);
+    ds_allocator_destroy(server->allocator);
+}
+
+static void
+output_handle_destroy(struct wl_listener *listener,
+        void *data __attribute__((unused)))
+{
+    struct server *server =
+        wl_container_of(listener, server, output_destroy);
+    wl_display_terminate(server->display);
+}
+
+static void
+paint_pixels(void *image, int padding, int width, int height, uint32_t time)
+{
+       const int halfh = padding + (height - padding * 2) / 2;
+       const int halfw = padding + (width - padding * 2) / 2;
+       int ir, or;
+       uint32_t *pixel = image;
+       int y;
+
+       /* squared radii thresholds */
+       or = (halfw < halfh ? halfw : halfh) - 8;
+       ir = or - 32;
+       or *= or;
+       ir *= ir;
+
+       pixel += padding * width;
+       for (y = padding; y < height - padding; y++) {
+               int x;
+               int y2 = (y - halfh) * (y - halfh);
+
+               pixel += padding;
+               for (x = padding; x < width - padding; x++) {
+                       uint32_t v;
+
+                       /* squared distance from center */
+                       int r2 = (x - halfw) * (x - halfw) + y2;
+
+                       if (r2 < ir)
+                               v = (r2 / 32 + time / 64) * 0x0080401;
+                       else if (r2 < or)
+                               v = (y + time / 32) * 0x0080401;
+                       else
+                               v = (x + time / 16) * 0x0080401;
+                       v &= 0x00ffffff;
+
+                       /* cross if compositor uses X from XRGB as alpha */
+                       if (abs(x - y) > 6 && abs(x + y - height) > 6)
+                               v |= 0xff000000;
+
+                       *pixel++ = v;
+               }
+
+               pixel += padding;
+       }
+}
+
+static inline int64_t                                       
+timespec_to_msec(const struct timespec *a)                  
+{                                                           
+    return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
+}                                                           
+
+static void
+output_handle_frame(struct wl_listener *listener,
+        void *data __attribute__((unused)))
+{
+    struct server *server =
+        wl_container_of(listener, server, output_frame);
+    draw_output(server);
+}
+
+static void
+draw_output(struct server *server)
+{
+    struct ds_buffer *buffer;
+    void *data;
+    uint32_t format;
+    size_t stride;
+    struct timespec now;                 
+    uint32_t frame_time_msec;
+
+    ds_dbg("Redraw output");
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    frame_time_msec = timespec_to_msec(&now);
+
+    buffer = ds_swapchain_acquire(server->swapchain, NULL);
+    assert(buffer);
+
+    assert(ds_buffer_begin_data_ptr_access(buffer,
+                0, &data, &format, &stride) == true);
+
+    paint_pixels(data, 20, server->width, server->height, frame_time_msec);
+
+    ds_buffer_end_data_ptr_access(buffer);
+
+    ds_output_attach_buffer(server->output, buffer);
+    ds_output_commit(server->output);
+
+    if (server->front_buffer)
+        ds_buffer_unlock(server->front_buffer);
+
+    server->front_buffer = buffer;
+}
+
+static int
+stdin_dispatch(int fd, uint32_t mask, void *data)
+{
+    struct server *server = data;
+
+    wl_display_terminate(server->display);
+
+    return 1;
+}
index 24506b6..36bfda9 100644 (file)
@@ -15,6 +15,7 @@ libds_version_minor = version_arr[1]
 libds_version_patch = version_arr[2]
 
 dir_prefix = get_option('prefix')
+libds_bindir = join_paths(dir_prefix, get_option('bindir'))
 
 libds_inc = include_directories('include')
 common_inc = [ include_directories('.'), libds_inc ]
@@ -24,8 +25,10 @@ cdata.set('LIBDS_VERSION_MAJOR', libds_version_major)
 cdata.set('LIBDS_VERSION_MINOR', libds_version_minor)
 cdata.set('LIBDS_VERSION_PATCH', libds_version_patch)
 
+
 subdir('include')
 subdir('src')
+subdir('examples')
 
 configure_file(output: 'config.h', install: false, configuration: cdata)
 
index aaf79b3..69d58f6 100644 (file)
@@ -57,3 +57,4 @@ ninja -C builddir install
 %{_includedir}/*
 %{_libdir}/pkgconfig/libds.pc
 %{_libdir}/libds.so
+%{_bindir}/*