From e884340a9a401eb3928ae0e0e6da5c56040f8bbd Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 24 Feb 2022 15:01:35 +0900 Subject: [PATCH] Add an example of tdm backend Change-Id: I836ba2b5b88d3799c7b095051e255779d653fa10 --- examples/meson.build | 14 ++- examples/tdm-backend.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 3 + packaging/libds.spec | 1 + 4 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 examples/tdm-backend.c diff --git a/examples/meson.build b/examples/meson.build index a107a77..530cbdd 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -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 index 0000000..15f5711 --- /dev/null +++ b/examples/tdm-backend.c @@ -0,0 +1,248 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/meson.build b/meson.build index 24506b6..36bfda9 100644 --- a/meson.build +++ b/meson.build @@ -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) diff --git a/packaging/libds.spec b/packaging/libds.spec index aaf79b3..69d58f6 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -57,3 +57,4 @@ ninja -C builddir install %{_includedir}/* %{_libdir}/pkgconfig/libds.pc %{_libdir}/libds.so +%{_bindir}/* -- 2.7.4