From fd092a63621eb215ad68aff239df556a7be8a677 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 4 Mar 2022 10:44:57 +0900 Subject: [PATCH 01/16] backend/tdm: Split commit function into small functions No functional changes. It improves readability. Change-Id: Ib762d10a2ad085da18b2c21e00cbb66f2193d345 --- src/libds/backend/tdm/output.c | 135 ++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 56 deletions(-) diff --git a/src/libds/backend/tdm/output.c b/src/libds/backend/tdm/output.c index a67c618..bc931d7 100644 --- a/src/libds/backend/tdm/output.c +++ b/src/libds/backend/tdm/output.c @@ -11,6 +11,9 @@ static bool tdm_output_init_modes(struct ds_tdm_output *output); static void tdm_output_destroy(struct ds_tdm_output *output); static void tdm_output_init_hwc(struct ds_tdm_output *output); static bool tdm_output_update_mode(struct ds_tdm_output *output); +static bool tdm_output_set_pending_fb(struct ds_tdm_output *output, + struct ds_buffer *ds_buffer); +static bool tdm_output_hwc_commit(struct ds_tdm_output *output); struct ds_tdm_output * create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) @@ -167,25 +170,10 @@ tdm_output_attach_back_buffer(struct ds_tdm_output *output, output->back_buffer = buffer; } -static void -tdm_output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - struct ds_tdm_output *output; - - output = user_data; - - tdm_output_update_front_buffer(output); - - wl_signal_emit(&output->base.events.frame, &output->base); -} - static bool tdm_output_iface_commit(struct ds_output *ds_output) { struct ds_tdm_output *output; - struct ds_tdm_buffer *buffer; - struct ds_buffer *ds_buffer; output = tdm_output_from_output(ds_output); @@ -197,51 +185,19 @@ tdm_output_iface_commit(struct ds_output *ds_output) } if (ds_output->pending.committed & DS_OUTPUT_STATE_BUFFER) { - tdm_region fb_damage; - tdm_error err; - uint32_t num_changes; - - ds_buffer = ds_output->pending.buffer; - buffer = get_or_create_tdm_buffer(output->backend, ds_buffer); - if (!buffer) - return false; - - memset(&fb_damage, 0, sizeof(fb_damage)); - err = tdm_hwc_set_client_target_buffer(output->tdm.hwc, - buffer->surface, fb_damage); - if (err != TDM_ERROR_NONE) { - ds_err("Could not set hwc client target buffer"); - ds_buffer_unlock(buffer->buffer); - return false; - } - - err = tdm_hwc_validate(output->tdm.hwc, NULL, 0, &num_changes); - if (err != TDM_ERROR_NONE) { - ds_err("Could not hwc validate"); - ds_buffer_unlock(buffer->buffer); - return false; - } - - err = tdm_hwc_accept_validation(output->tdm.hwc); - if (err != TDM_ERROR_NONE) { - ds_err("Could not hwc accept validation"); - ds_buffer_unlock(buffer->buffer); - return false; - } + if (!tdm_output_set_pending_fb(output, ds_output->pending.buffer)) + ds_err("Could not update buffer"); + } - err = tdm_hwc_commit(output->tdm.hwc, 0, tdm_output_hwc_commit_handler, - output); - if (err != TDM_ERROR_NONE) { - ds_err("Could not hwc commit"); - ds_buffer_unlock(buffer->buffer); - return false; + if (!tdm_output_hwc_commit(output)) { + ds_err("Could not commit tdm output"); + if (output->back_buffer) { + tdm_buffer_release(output->back_buffer); } - - tdm_output_attach_back_buffer(output, buffer); - - ds_dbg("Swap Buffer!!!!!"); } + ds_dbg("Swap Buffer!!!!!"); + return true; } @@ -346,3 +302,70 @@ tdm_output_update_mode(struct ds_tdm_output *output) return true; } + +static bool +tdm_output_set_pending_fb(struct ds_tdm_output *output, + struct ds_buffer *ds_buffer) +{ + struct ds_tdm_buffer *buffer; + tdm_region fb_damage; + tdm_error err; + + buffer = get_or_create_tdm_buffer(output->backend, ds_buffer); + if (!buffer) + return false; + + memset(&fb_damage, 0, sizeof(fb_damage)); + err = tdm_hwc_set_client_target_buffer(output->tdm.hwc, + buffer->surface, fb_damage); + if (err != TDM_ERROR_NONE) { + ds_err("Could not set hwc client target buffer"); + ds_buffer_unlock(buffer->buffer); + return false; + } + + tdm_output_attach_back_buffer(output, buffer); + + return true; +} + +static void +tdm_output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + struct ds_tdm_output *output; + + output = user_data; + + tdm_output_update_front_buffer(output); + + wl_signal_emit(&output->base.events.frame, &output->base); +} + +static bool +tdm_output_hwc_commit(struct ds_tdm_output *output) +{ + tdm_error err; + uint32_t num_changes; + + err = tdm_hwc_validate(output->tdm.hwc, NULL, 0, &num_changes); + if (err != TDM_ERROR_NONE) { + ds_err("Could not hwc validate"); + return false; + } + + err = tdm_hwc_accept_validation(output->tdm.hwc); + if (err != TDM_ERROR_NONE) { + ds_err("Could not hwc accept validation"); + return false; + } + + err = tdm_hwc_commit(output->tdm.hwc, 0, tdm_output_hwc_commit_handler, + output); + if (err != TDM_ERROR_NONE) { + ds_err("Could not hwc commit"); + return false; + } + + return true; +} -- 2.7.4 From 5b464e44bdc24e2caf8408279f9131ecaa29d375 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 4 Mar 2022 10:49:50 +0900 Subject: [PATCH 02/16] backend/tdm: Remove prefix tdm from static functions It's to avoid confusion with tdm api. For static functions, the names chosen aren't as important. Change-Id: I917a027f0c94c67c18d3b7823bc216eed0080b60 --- src/libds/backend/tdm/output.c | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libds/backend/tdm/output.c b/src/libds/backend/tdm/output.c index bc931d7..a05d2c9 100644 --- a/src/libds/backend/tdm/output.c +++ b/src/libds/backend/tdm/output.c @@ -7,13 +7,13 @@ #include static const struct ds_output_interface tdm_output_iface; -static bool tdm_output_init_modes(struct ds_tdm_output *output); -static void tdm_output_destroy(struct ds_tdm_output *output); -static void tdm_output_init_hwc(struct ds_tdm_output *output); -static bool tdm_output_update_mode(struct ds_tdm_output *output); -static bool tdm_output_set_pending_fb(struct ds_tdm_output *output, +static bool output_init_modes(struct ds_tdm_output *output); +static void output_destroy(struct ds_tdm_output *output); +static void output_init_hwc(struct ds_tdm_output *output); +static bool output_update_mode(struct ds_tdm_output *output); +static bool output_set_pending_fb(struct ds_tdm_output *output, struct ds_buffer *ds_buffer); -static bool tdm_output_hwc_commit(struct ds_tdm_output *output); +static bool output_hwc_commit(struct ds_tdm_output *output); struct ds_tdm_output * create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) @@ -42,7 +42,7 @@ create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) if (conn == TDM_OUTPUT_CONN_STATUS_CONNECTED) { output->status = DS_TDM_OUTPUT_CONNECTED; - if (!tdm_output_init_modes(output)) { + if (!output_init_modes(output)) { ds_err("Could not initialize modes of tdm output(%p)", tdm_output); goto err_status; @@ -53,7 +53,7 @@ create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) } if (tdm_output_get_hwc(output->tdm.output, NULL) != NULL) - tdm_output_init_hwc(output); + output_init_hwc(output); ds_inf("TDM output(%p) created: hwc(%p)", output, output->tdm.hwc); @@ -73,12 +73,12 @@ tdm_output_from_output(struct ds_output *ds_output) } static void -tdm_output_iface_destroy(struct ds_output *ds_output) +output_iface_destroy(struct ds_output *ds_output) { struct ds_tdm_output *output; output = tdm_output_from_output(ds_output); - tdm_output_destroy(output); + output_destroy(output); } void @@ -153,7 +153,7 @@ tdm_buffer_release(struct ds_tdm_buffer *buffer) } static void -tdm_output_update_front_buffer(struct ds_tdm_output *output) +output_update_front_buffer(struct ds_tdm_output *output) { if (output->front_buffer) tdm_buffer_release(output->front_buffer); @@ -162,7 +162,7 @@ tdm_output_update_front_buffer(struct ds_tdm_output *output) } static void -tdm_output_attach_back_buffer(struct ds_tdm_output *output, +output_attach_back_buffer(struct ds_tdm_output *output, struct ds_tdm_buffer *buffer) { if (output->back_buffer) @@ -171,25 +171,25 @@ tdm_output_attach_back_buffer(struct ds_tdm_output *output, } static bool -tdm_output_iface_commit(struct ds_output *ds_output) +output_iface_commit(struct ds_output *ds_output) { struct ds_tdm_output *output; output = tdm_output_from_output(ds_output); if (ds_output->pending.committed & DS_OUTPUT_STATE_MODE) { - if (!tdm_output_update_mode(output)) { + if (!output_update_mode(output)) { ds_err("Could not update TDM mode"); return false; } } if (ds_output->pending.committed & DS_OUTPUT_STATE_BUFFER) { - if (!tdm_output_set_pending_fb(output, ds_output->pending.buffer)) + if (!output_set_pending_fb(output, ds_output->pending.buffer)) ds_err("Could not update buffer"); } - if (!tdm_output_hwc_commit(output)) { + if (!output_hwc_commit(output)) { ds_err("Could not commit tdm output"); if (output->back_buffer) { tdm_buffer_release(output->back_buffer); @@ -203,12 +203,12 @@ tdm_output_iface_commit(struct ds_output *ds_output) static const struct ds_output_interface tdm_output_iface = { - .destroy = tdm_output_iface_destroy, - .commit = tdm_output_iface_commit, + .destroy = output_iface_destroy, + .commit = output_iface_commit, }; static void -tdm_output_destroy(struct ds_tdm_output *output) +output_destroy(struct ds_tdm_output *output) { struct ds_tdm_output_mode *mode, *mode_tmp; @@ -227,7 +227,7 @@ tdm_output_destroy(struct ds_tdm_output *output) } static bool -tdm_output_init_modes(struct ds_tdm_output *output) +output_init_modes(struct ds_tdm_output *output) { struct ds_tdm_output_mode *mode; const tdm_output_mode *tdm_modes, *tdm_mode; @@ -274,7 +274,7 @@ tdm_output_init_modes(struct ds_tdm_output *output) } static void -tdm_output_init_hwc(struct ds_tdm_output *output) +output_init_hwc(struct ds_tdm_output *output) { tdm_error err; @@ -286,7 +286,7 @@ tdm_output_init_hwc(struct ds_tdm_output *output) } static bool -tdm_output_update_mode(struct ds_tdm_output *output) +output_update_mode(struct ds_tdm_output *output) { const struct ds_tdm_output_mode *mode; tdm_error err; @@ -304,7 +304,7 @@ tdm_output_update_mode(struct ds_tdm_output *output) } static bool -tdm_output_set_pending_fb(struct ds_tdm_output *output, +output_set_pending_fb(struct ds_tdm_output *output, struct ds_buffer *ds_buffer) { struct ds_tdm_buffer *buffer; @@ -324,26 +324,26 @@ tdm_output_set_pending_fb(struct ds_tdm_output *output, return false; } - tdm_output_attach_back_buffer(output, buffer); + output_attach_back_buffer(output, buffer); return true; } static void -tdm_output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, +output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { struct ds_tdm_output *output; output = user_data; - tdm_output_update_front_buffer(output); + output_update_front_buffer(output); wl_signal_emit(&output->base.events.frame, &output->base); } static bool -tdm_output_hwc_commit(struct ds_tdm_output *output) +output_hwc_commit(struct ds_tdm_output *output) { tdm_error err; uint32_t num_changes; @@ -360,7 +360,7 @@ tdm_output_hwc_commit(struct ds_tdm_output *output) return false; } - err = tdm_hwc_commit(output->tdm.hwc, 0, tdm_output_hwc_commit_handler, + err = tdm_hwc_commit(output->tdm.hwc, 0, output_hwc_commit_handler, output); if (err != TDM_ERROR_NONE) { ds_err("Could not hwc commit"); -- 2.7.4 From d6c0be1bfe70ede248dbbfe1f752f43776d97560 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 4 Mar 2022 14:25:20 +0900 Subject: [PATCH 03/16] Fix formatting Change-Id: I01c89e5adaa5180a116cc61fedce055bb90290bd --- src/libds/allocator.c | 1 + src/libds/allocator/shm.c | 9 ++++++--- src/libds/allocator/tbm.c | 6 +++--- src/libds/backend.c | 4 +++- src/libds/backend/tdm/backend.c | 14 ++++++------- src/libds/backend/tdm/output.c | 13 ++++++------ src/libds/backend/tdm/tdm.h | 1 + src/libds/backend/wayland/backend.c | 17 ++++++++-------- src/libds/backend/wayland/output.c | 11 ++++++---- src/libds/buffer.c | 12 ++++++----- src/libds/client_buffer.h | 3 ++- src/libds/client_buffer/shm_client_buffer.c | 11 ++++++---- src/libds/compositor.c | 12 +++++++---- src/libds/log.c | 9 +++++++-- src/libds/pixel_format.c | 1 + src/libds/presentation.c | 7 ++++--- src/libds/region.c | 9 +++++---- src/libds/subcompositor.c | 11 ++++++---- src/libds/surface/subsurface.c | 7 +++++-- src/libds/surface/surface-private.h | 1 + src/libds/surface/surface.c | 31 +++++++++++++++++++---------- src/libds/swapchain.c | 2 +- src/libds/util/time.c | 4 +++- src/libds/xdg_shell/xdg_shell.c | 17 ++++++++-------- src/libds/xdg_shell/xdg_shell.h | 2 +- src/libds/xdg_shell/xdg_surface.c | 4 +++- src/libds/xdg_shell/xdg_toplevel.c | 14 +++++++------ 27 files changed, 142 insertions(+), 91 deletions(-) diff --git a/src/libds/allocator.c b/src/libds/allocator.c index 34c0aa7..c9769be 100644 --- a/src/libds/allocator.c +++ b/src/libds/allocator.c @@ -1,5 +1,6 @@ #include #include + #include #include "libds/log.h" diff --git a/src/libds/allocator/shm.c b/src/libds/allocator/shm.c index a0acd0c..3fad474 100644 --- a/src/libds/allocator/shm.c +++ b/src/libds/allocator/shm.c @@ -2,6 +2,7 @@ #include #include #include + #include #include @@ -127,6 +128,7 @@ shm_allocator_create_buffer(struct ds_allocator *ds_allocator, int width, int height, uint32_t format) { struct ds_shm_buffer *buffer; + int bytes_per_pixel, stride; buffer = calloc(1, sizeof *buffer); if (!buffer) @@ -135,8 +137,8 @@ shm_allocator_create_buffer(struct ds_allocator *ds_allocator, ds_buffer_init(&buffer->base, &shm_buffer_interface, width, height); // FIXME - int bytes_per_pixel = 4; - int stride = width * bytes_per_pixel; + bytes_per_pixel = 4; + stride = width * bytes_per_pixel; buffer->size = stride * height; buffer->shm.fd = allocate_shm_file(buffer->size); if (buffer->shm.fd < 0) { @@ -164,7 +166,8 @@ shm_allocator_create_buffer(struct ds_allocator *ds_allocator, return &buffer->base; } -static const struct ds_allocator_interface shm_allocator_iface = { +static const struct ds_allocator_interface shm_allocator_iface = +{ .destroy = shm_allocator_destroy, .create_buffer = shm_allocator_create_buffer, }; diff --git a/src/libds/allocator/tbm.c b/src/libds/allocator/tbm.c index f4d0702..dc3be42 100644 --- a/src/libds/allocator/tbm.c +++ b/src/libds/allocator/tbm.c @@ -1,8 +1,8 @@ #include #include + #include #include - #include #include @@ -136,7 +136,6 @@ static const struct ds_buffer_interface tbm_buffer_iface = .end_data_ptr_access = tbm_buffer_end_data_ptr_access, }; - static void tbm_allocator_destroy(struct ds_allocator *ds_allocator) { @@ -171,7 +170,8 @@ tbm_allocator_create_buffer(struct ds_allocator *ds_allocator, return &buffer->base; } -static const struct ds_allocator_interface tbm_allocator_iface = { +static const struct ds_allocator_interface tbm_allocator_iface = +{ .destroy = tbm_allocator_destroy, .create_buffer = tbm_allocator_create_buffer, }; diff --git a/src/libds/backend.c b/src/libds/backend.c index d52a8d2..ee2a912 100644 --- a/src/libds/backend.c +++ b/src/libds/backend.c @@ -1,4 +1,5 @@ #include + #include #include "libds/interfaces/backend.h" @@ -41,7 +42,8 @@ ds_backend_add_new_output_listener(struct ds_backend *backend, } void -ds_backend_init(struct ds_backend *backend, const struct ds_backend_interface *iface) +ds_backend_init(struct ds_backend *backend, + const struct ds_backend_interface *iface) { backend->iface = iface; wl_signal_init(&backend->events.destroy); diff --git a/src/libds/backend/tdm/backend.c b/src/libds/backend/tdm/backend.c index c893702..e756ac1 100644 --- a/src/libds/backend/tdm/backend.c +++ b/src/libds/backend/tdm/backend.c @@ -2,9 +2,11 @@ #include #include "libds/log.h" + #include "tdm.h" static const struct ds_backend_interface tdm_backend_iface; + static void tdm_backend_handle_display_destroy(struct wl_listener *listener, void *data); static void tdm_backend_destroy(struct ds_tdm_backend *tdm); @@ -79,13 +81,11 @@ tdm_backend_destroy(struct ds_tdm_backend *tdm) struct ds_tdm_output *output, *tmp_output; struct ds_tdm_buffer *buffer, *tmp_buffer; - wl_list_for_each_safe(output, tmp_output, &tdm->outputs, link) { + wl_list_for_each_safe(output, tmp_output, &tdm->outputs, link) ds_output_destroy(&output->base); - } - wl_list_for_each_safe(buffer, tmp_buffer, &tdm->buffers, link) { + wl_list_for_each_safe(buffer, tmp_buffer, &tdm->buffers, link) destroy_tdm_buffer(buffer); - } wl_list_remove(&tdm->display_destroy.link); wl_event_source_remove(tdm->tdm_event); @@ -149,7 +149,8 @@ tdm_backend_iface_destroy(struct ds_backend *backend) tdm_backend_destroy(tdm); } -static const struct ds_backend_interface tdm_backend_iface = { +static const struct ds_backend_interface tdm_backend_iface = +{ .start = tdm_backend_iface_start, .destroy = tdm_backend_iface_destroy, .get_drm_fd = NULL, @@ -167,9 +168,8 @@ tdm_backend_handle_display_destroy(struct wl_listener *listener, void *data) static int tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data) { - struct ds_tdm_backend *tdm; + struct ds_tdm_backend *tdm = data; - tdm = data; tdm_display_handle_events(tdm->tdm_display); return 0; diff --git a/src/libds/backend/tdm/output.c b/src/libds/backend/tdm/output.c index a05d2c9..958b8ce 100644 --- a/src/libds/backend/tdm/output.c +++ b/src/libds/backend/tdm/output.c @@ -1,10 +1,12 @@ #include #include +#include + #include "libds/log.h" #include "libds/allocator/tbm.h" + #include "tdm.h" -#include static const struct ds_output_interface tdm_output_iface; static bool output_init_modes(struct ds_tdm_output *output); @@ -114,9 +116,8 @@ create_tdm_buffer(struct ds_tdm_backend *backend, struct ds_buffer *ds_buffer) } buffer = calloc(1, sizeof *buffer); - if (!buffer) { + if (!buffer) return NULL; - } buffer->surface = surface; buffer->buffer = ds_buffer_lock(ds_buffer); @@ -241,7 +242,7 @@ output_init_modes(struct ds_tdm_output *output) return false; } - ds_inf("Detected modes:"); + ds_dbg("Detected modes:"); for (i = 0; i < num_modes; i++) { tdm_mode = &tdm_modes[i]; @@ -333,9 +334,7 @@ static void output_hwc_commit_handler(tdm_hwc *hwc, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { - struct ds_tdm_output *output; - - output = user_data; + struct ds_tdm_output *output = user_data; output_update_front_buffer(output); diff --git a/src/libds/backend/tdm/tdm.h b/src/libds/backend/tdm/tdm.h index 2b1c1e4..1c80ef9 100644 --- a/src/libds/backend/tdm/tdm.h +++ b/src/libds/backend/tdm/tdm.h @@ -2,6 +2,7 @@ #define DS_BACKEND_TDM_H #include + #include #include "libds/interfaces/backend.h" diff --git a/src/libds/backend/wayland/backend.c b/src/libds/backend/wayland/backend.c index 9b6cd3a..778ca1c 100644 --- a/src/libds/backend/wayland/backend.c +++ b/src/libds/backend/wayland/backend.c @@ -1,15 +1,16 @@ #include #include #include + #include #include -#include "backend.h" #include "libds/log.h" #include "libds/output.h" - #include "xdg-shell-client-protocol.h" +#include "backend.h" + static const struct ds_backend_interface wl_backend_interface; static void wl_backend_handle_display_destroy(struct wl_listener *listener, void *data); @@ -86,13 +87,11 @@ wl_backend_destroy(struct ds_wl_backend *backend) ds_dbg("Destroy wayland backend(%p)", backend); - wl_list_for_each_safe(output, tmp_output, &backend->outputs, link) { + wl_list_for_each_safe(output, tmp_output, &backend->outputs, link) ds_output_destroy(&output->base); - } - wl_list_for_each_safe(buffer, tmp_buffer, &backend->buffers, link) { + wl_list_for_each_safe(buffer, tmp_buffer, &backend->buffers, link) destroy_wl_buffer(buffer); - } ds_backend_finish(&backend->base); @@ -118,7 +117,8 @@ wl_backend_iface_destroy(struct ds_backend *backend) wl_backend_destroy(wl_backend); } -static const struct ds_backend_interface wl_backend_interface = { +static const struct ds_backend_interface wl_backend_interface = +{ .start = NULL, .destroy = wl_backend_iface_destroy, .get_drm_fd = NULL, @@ -185,7 +185,8 @@ registry_handle_global_remove(void *data, struct wl_registry *registry, // TODO } -static const struct wl_registry_listener registry_listener = { +static const struct wl_registry_listener registry_listener = +{ .global = registry_handle_global, .global_remove = registry_handle_global_remove, }; diff --git a/src/libds/backend/wayland/output.c b/src/libds/backend/wayland/output.c index b411dad..bc18875 100644 --- a/src/libds/backend/wayland/output.c +++ b/src/libds/backend/wayland/output.c @@ -1,13 +1,14 @@ #include #include + #include -#include "backend.h" #include "libds/log.h" #include "libds/output.h" - #include "xdg-shell-client-protocol.h" +#include "backend.h" + const struct ds_output_interface wl_output_iface; static const struct xdg_surface_listener wl_output_xdg_surface_listener; static const struct xdg_toplevel_listener wl_output_xdg_toplevel_listener; @@ -154,7 +155,8 @@ buffer_handle_release(void *data, struct wl_buffer *wl_buffer) ds_buffer_unlock(buffer->buffer); } -static const struct wl_buffer_listener buffer_listener = { +static const struct wl_buffer_listener buffer_listener = +{ .release = buffer_handle_release, }; @@ -223,7 +225,8 @@ surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) wl_signal_emit(&output->base.events.frame, &output->base); } -static const struct wl_callback_listener frame_listener = { +static const struct wl_callback_listener frame_listener = +{ .done = surface_frame_callback }; diff --git a/src/libds/buffer.c b/src/libds/buffer.c index 167d3a7..60b9925 100644 --- a/src/libds/buffer.c +++ b/src/libds/buffer.c @@ -1,11 +1,12 @@ #include #include -#include "buffer.h" -#include "client_buffer.h" #include "libds/log.h" #include "libds/interfaces/buffer.h" +#include "buffer.h" +#include "client_buffer.h" + static struct wl_array buffer_resource_interfaces = {0}; static void buffer_consider_destroy(struct ds_buffer *buffer); @@ -14,8 +15,8 @@ static const struct ds_buffer_resource_interface * get_buffer_resource_iface(struct wl_resource *resource); WL_EXPORT void -ds_buffer_init(struct ds_buffer *buffer, const struct ds_buffer_interface *iface, - int width, int height) +ds_buffer_init(struct ds_buffer *buffer, + const struct ds_buffer_interface *iface, int width, int height) { buffer->iface = iface; buffer->width = width; @@ -99,7 +100,8 @@ ds_buffer_begin_data_ptr_access(struct ds_buffer *buffer, uint32_t flags, assert(!buffer->accessing_data_ptr); if (!buffer->iface->begin_data_ptr_access) return false; - if (!buffer->iface->begin_data_ptr_access(buffer, flags, data, format, stride)) + if (!buffer->iface->begin_data_ptr_access(buffer, + flags, data, format, stride)) return false; buffer->accessing_data_ptr = true; return true; diff --git a/src/libds/client_buffer.h b/src/libds/client_buffer.h index cf390aa..a2aef6a 100644 --- a/src/libds/client_buffer.h +++ b/src/libds/client_buffer.h @@ -3,10 +3,11 @@ #include -#include "util.h" #include "libds/buffer.h" #include "libds/interfaces/buffer.h" +#include "util.h" + struct ds_shm_client_buffer { struct ds_buffer base; diff --git a/src/libds/client_buffer/shm_client_buffer.c b/src/libds/client_buffer/shm_client_buffer.c index 14bb745..6d52fb9 100644 --- a/src/libds/client_buffer/shm_client_buffer.c +++ b/src/libds/client_buffer/shm_client_buffer.c @@ -1,10 +1,12 @@ #include #include + #include +#include "libds/log.h" + #include "pixel_format.h" #include "buffer.h" -#include "libds/log.h" #include "client_buffer.h" static void @@ -37,7 +39,6 @@ shm_client_buffer_resource_handle_destroy(struct wl_listener *listener, struct ds_shm_client_buffer *buffer; buffer = wl_container_of(listener, buffer, listener.resource_destroy); - buffer->resource = NULL; buffer->shm_buffer = NULL; wl_list_remove(&buffer->listener.resource_destroy.link); @@ -83,8 +84,9 @@ shm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, *data = wl_shm_buffer_get_data(buffer->shm_buffer); wl_shm_buffer_begin_access(buffer->shm_buffer); } - else + else { return false; + } return true; } @@ -99,7 +101,8 @@ shm_client_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer) wl_shm_buffer_end_access(buffer->shm_buffer); } -static const struct ds_buffer_interface shm_client_buffer_iface = { +static const struct ds_buffer_interface shm_client_buffer_iface = +{ .destroy = shm_client_buffer_destroy, .begin_data_ptr_access = shm_client_buffer_begin_data_ptr_access, .end_data_ptr_access = shm_client_buffer_end_data_ptr_access, diff --git a/src/libds/compositor.c b/src/libds/compositor.c index 64dd363..64b9a99 100644 --- a/src/libds/compositor.c +++ b/src/libds/compositor.c @@ -2,6 +2,7 @@ #include #include "libds/log.h" + #include "subcompositor.h" #include "surface.h" #include "region.h" @@ -85,9 +86,10 @@ static void compositor_handle_create_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id) { - struct ds_compositor *compositor = wl_resource_get_user_data(resource); + struct ds_compositor *compositor; struct ds_surface *surface; + compositor = wl_resource_get_user_data(resource); surface = ds_surface_create(client, wl_resource_get_version(resource), id); if (!surface) { @@ -105,7 +107,8 @@ compositor_handle_create_region(struct wl_client *client, ds_region_add(client, wl_resource_get_version(resource), id); } -static const struct wl_compositor_interface compositor_impl = { +static const struct wl_compositor_interface compositor_impl = +{ .create_surface = compositor_handle_create_surface, .create_region = compositor_handle_create_region, }; @@ -130,8 +133,9 @@ static void compositor_bind(struct wl_client *client, void *data, static void compositor_handle_display_destroy(struct wl_listener *listener, void *data) { - struct ds_compositor *compositor = - wl_container_of(listener, compositor, display_destroy); + struct ds_compositor *compositor; + + compositor = wl_container_of(listener, compositor, display_destroy); ds_dbg("Destroy compositor(%p)", compositor); diff --git a/src/libds/log.c b/src/libds/log.c index 2777f9a..67386af 100644 --- a/src/libds/log.c +++ b/src/libds/log.c @@ -4,6 +4,7 @@ #include #include #include + #include #include "libds/log.h" @@ -51,6 +52,7 @@ WL_EXPORT void _ds_log(enum ds_log_level level, const char *fmt, ...) { va_list args; + va_start(args, fmt); log_callback(level, fmt, args); va_end(args); @@ -66,11 +68,12 @@ static void log_stderr(enum ds_log_level level, const char *fmt, va_list args) { bool colored_tty = false; + unsigned c; if (level > log_level) return; - unsigned c = (level < DS_LOG_LEVEL_LAST) ? level : DS_LOG_LEVEL_LAST - 1; + c = (level < DS_LOG_LEVEL_LAST) ? level : DS_LOG_LEVEL_LAST - 1; colored_tty = colored && isatty(STDERR_FILENO); if (colored_tty) @@ -89,7 +92,9 @@ static void log_wl(const char *fmt, va_list args) { static char ds_fmt[1024]; - int n = snprintf(ds_fmt, sizeof(ds_fmt), "[wayland] %s", fmt); + int n; + + n = snprintf(ds_fmt, sizeof(ds_fmt), "[wayland] %s", fmt); if (n > 0 && ds_fmt[n - 1] == '\n') ds_fmt[n - 1] = '\0'; _ds_vlog(DS_INF, ds_fmt, args); diff --git a/src/libds/pixel_format.c b/src/libds/pixel_format.c index 29da532..8676bec 100644 --- a/src/libds/pixel_format.c +++ b/src/libds/pixel_format.c @@ -1,4 +1,5 @@ #include + #include "pixel_format.h" uint32_t diff --git a/src/libds/presentation.c b/src/libds/presentation.c index d94ad04..54d10d9 100644 --- a/src/libds/presentation.c +++ b/src/libds/presentation.c @@ -1,3 +1,5 @@ +// TODO + #include "libds-private.h" #include "presentation-time-protocol.h" @@ -29,8 +31,6 @@ struct ds_presentation_feedback uint32_t psf_flags; }; - - static void presentation_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); static void handle_display_destroy(struct wl_listener *listener, void *data); @@ -77,7 +77,8 @@ presentation_handle_feedback(struct wl_client *client, surface = ds_surface_from_resource(surface_resource); } -static const struct wp_presentation_interface presentation_impl = { +static const struct wp_presentation_interface presentation_impl = +{ .destroy = presentation_handle_destroy, .feedback = presentation_handle_feedback, }; diff --git a/src/libds/region.c b/src/libds/region.c index 27d30da..92fe003 100644 --- a/src/libds/region.c +++ b/src/libds/region.c @@ -3,9 +3,10 @@ #include #include -#include "region.h" #include "libds/log.h" +#include "region.h" + static const struct wl_region_interface region_impl; static void region_handle_resource_destroy(struct wl_resource *resource); @@ -127,9 +128,8 @@ ds_region_scale_xy(pixman_region32_t *dst, pixman_region32_t *src, pixman_box32_t *src_rects, *dst_rects; int nrects, i; - if (scale_x == 1.0 && scale_y == 1.0) { + if (scale_x == 1.0 && scale_y == 1.0) pixman_region32_copy(dst, src); - } src_rects = pixman_region32_rectangles(src, &nrects); dst_rects = malloc(nrects * sizeof *dst_rects); @@ -181,7 +181,8 @@ region_subtract(struct wl_client *client, struct wl_resource *resource, pixman_region32_fini(&rect); } -static const struct wl_region_interface region_impl = { +static const struct wl_region_interface region_impl = +{ .destroy = region_destroy, .add = region_add, .subtract = region_subtract, diff --git a/src/libds/subcompositor.c b/src/libds/subcompositor.c index 717fd33..9e821b3 100644 --- a/src/libds/subcompositor.c +++ b/src/libds/subcompositor.c @@ -1,6 +1,7 @@ +#include "libds/log.h" + #include "subcompositor.h" #include "surface.h" -#include "libds/log.h" #define SUBCOMPOSITOR_VERSION 1 @@ -40,9 +41,10 @@ subcompositor_handle_get_subsurface(struct wl_client *client, struct wl_resource *surface_resource, struct wl_resource *parent_resource) { - struct ds_surface *surface = ds_surface_from_resource(surface_resource); - struct ds_surface *parent = ds_surface_from_resource(parent_resource); + struct ds_surface *surface, *parent; + surface = ds_surface_from_resource(surface_resource); + parent = ds_surface_from_resource(parent_resource); if (surface == parent) { ds_inf("ds_surface(%p) cannot be its own parent", surface); wl_resource_post_error(resource, @@ -75,7 +77,8 @@ subcompositor_handle_get_subsurface(struct wl_client *client, wl_resource_get_version(resource), id); } -static const struct wl_subcompositor_interface subcompositor_impl = { +static const struct wl_subcompositor_interface subcompositor_impl = +{ .destroy = subcompositor_handle_destroy, .get_subsurface = subcompositor_handle_get_subsurface, }; diff --git a/src/libds/surface/subsurface.c b/src/libds/surface/subsurface.c index 4cc1ad8..2ec0dae 100644 --- a/src/libds/surface/subsurface.c +++ b/src/libds/surface/subsurface.c @@ -3,6 +3,7 @@ #include "libds/log.h" #include "libds/surface.h" + #include "surface-private.h" static const struct wl_subsurface_interface subsurface_impl; @@ -88,7 +89,8 @@ ds_subsurface_get_parent(struct ds_subsurface *subsurface) return subsurface->parent; } -static const struct ds_surface_role subsurface_role = { +static const struct ds_surface_role subsurface_role = +{ .name = "wl_subsurface", }; @@ -212,7 +214,8 @@ subsurface_handle_set_desync(struct wl_client *client, } } -static const struct wl_subsurface_interface subsurface_impl = { +static const struct wl_subsurface_interface subsurface_impl = +{ .destroy = subsurface_handle_destroy, .set_position = subsurface_handle_set_position, .place_above = subsurface_handle_place_above, diff --git a/src/libds/surface/surface-private.h b/src/libds/surface/surface-private.h index 78b2900..aee9547 100644 --- a/src/libds/surface/surface-private.h +++ b/src/libds/surface/surface-private.h @@ -2,6 +2,7 @@ #define DS_SURFACE_PRIVATE_H #include + #include #include diff --git a/src/libds/surface/surface.c b/src/libds/surface/surface.c index 32ab232..0333561 100644 --- a/src/libds/surface/surface.c +++ b/src/libds/surface/surface.c @@ -1,13 +1,13 @@ #include #include -#include "surface-private.h" -#include "region.h" -#include "util.h" - #include "libds/log.h" #include "libds/surface.h" +#include "region.h" +#include "util.h" +#include "surface-private.h" + #define CALLBACK_VERSION 1 static const struct wl_surface_interface surface_impl; @@ -335,9 +335,11 @@ static void surface_handle_set_input_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region_resource) { - struct ds_surface *surface = wl_resource_get_user_data(resource); + struct ds_surface *surface; pixman_region32_t *region; + surface = wl_resource_get_user_data(resource); + ds_dbg("ds_surface(%p) set input region", surface); surface->pending.committed |= DS_SURFACE_STATE_INPUT_REGION; @@ -379,7 +381,9 @@ static void surface_handle_set_buffer_transform(struct wl_client *client, struct wl_resource *resource, int32_t transform) { - struct ds_surface *surface = wl_resource_get_user_data(resource); + struct ds_surface *surface; + + surface = wl_resource_get_user_data(resource); ds_dbg("ds_surface(%p) set buffer transform(%d)", surface, transform); @@ -400,7 +404,9 @@ static void surface_handle_set_buffer_scale(struct wl_client *client, struct wl_resource *resource, int32_t scale) { - struct ds_surface *surface = wl_resource_get_user_data(resource); + struct ds_surface *surface; + + surface = wl_resource_get_user_data(resource); ds_dbg("ds_surface(%p) set buffer scale(%d)", surface, scale); @@ -421,7 +427,9 @@ surface_handle_damage_buffer(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) { - struct ds_surface *surface = wl_resource_get_user_data(resource); + struct ds_surface *surface; + + surface = wl_resource_get_user_data(resource); ds_dbg("ds_surface(%p) damage: x %d y %d width %d height %d", surface, x, y, width, height); @@ -438,7 +446,8 @@ surface_handle_damage_buffer(struct wl_client *client, x, y, width, height); } -static const struct wl_surface_interface surface_impl = { +static const struct wl_surface_interface surface_impl = +{ .destroy = surface_handle_destroy, .attach = surface_handle_attach, .damage = surface_handle_damage, @@ -454,7 +463,9 @@ static const struct wl_surface_interface surface_impl = { static void surface_handle_resource_destroy(struct wl_resource *resource) { - struct ds_surface *surface = wl_resource_get_user_data(resource); + struct ds_surface *surface; + + surface = wl_resource_get_user_data(resource); ds_inf("Destroy ds_surface %p (res %p)", surface, surface->resource); diff --git a/src/libds/swapchain.c b/src/libds/swapchain.c index 54e64cf..78a2ece 100644 --- a/src/libds/swapchain.c +++ b/src/libds/swapchain.c @@ -41,7 +41,7 @@ struct ds_swapchain * ds_swapchain_create(struct ds_allocator *alloc, int width, int height, uint32_t format) { - struct ds_swapchain *swapchain = NULL; + struct ds_swapchain *swapchain; swapchain = calloc(1, sizeof *swapchain); if (!swapchain) diff --git a/src/libds/util/time.c b/src/libds/util/time.c index 1b17516..afb0e89 100644 --- a/src/libds/util/time.c +++ b/src/libds/util/time.c @@ -3,6 +3,8 @@ #include #include -int64_t timespec_to_msec(const struct timespec *a) { +int64_t +timespec_to_msec(const struct timespec *a) +{ return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; } diff --git a/src/libds/xdg_shell/xdg_shell.c b/src/libds/xdg_shell/xdg_shell.c index b7cc8ff..a53684a 100644 --- a/src/libds/xdg_shell/xdg_shell.c +++ b/src/libds/xdg_shell/xdg_shell.c @@ -2,14 +2,16 @@ #include #include -#include "xdg_shell.h" #include "libds/log.h" #include "libds/xdg_shell.h" +#include "xdg_shell.h" + #define XDG_WM_BASE_VERSION 2 #define XDG_SHELL_PING_TIMEOUT 10000 -static void xdg_shell_handle_display_destroy(struct wl_listener *listener, void *data); +static void xdg_shell_handle_display_destroy(struct wl_listener *listener, + void *data); static void xdg_shell_bind(struct wl_client *wl_client, void *data, uint32_t verison, uint32_t id); @@ -126,7 +128,8 @@ xdg_shell_handle_pong(struct wl_client *wl_client, client->ping_serial = 0; } -static const struct xdg_wm_base_interface xdg_shell_impl = { +static const struct xdg_wm_base_interface xdg_shell_impl = +{ .destroy = xdg_shell_handle_destroy, .create_positioner = xdg_shell_handle_create_positioner, .get_xdg_surface = xdg_shell_handle_get_xdg_surface, @@ -150,11 +153,9 @@ xdg_client_handle_resource_destroy(struct wl_resource *resource) static int xdg_client_handle_ping_timeout(void *user_data) { - struct ds_xdg_client *client; + struct ds_xdg_client *client = user_data; struct ds_xdg_surface *surface; - client = user_data; - wl_list_for_each(surface, &client->surfaces, link) wl_signal_emit(&surface->events.ping_timeout, surface); @@ -181,11 +182,9 @@ static void xdg_shell_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { - struct ds_xdg_shell *shell; + struct ds_xdg_shell *shell = data; struct ds_xdg_client *client; - shell = data; - client = calloc(1, sizeof *client); if (client == NULL) { wl_client_post_no_memory(wl_client); diff --git a/src/libds/xdg_shell/xdg_shell.h b/src/libds/xdg_shell/xdg_shell.h index 6596ea2..ea67be7 100644 --- a/src/libds/xdg_shell/xdg_shell.h +++ b/src/libds/xdg_shell/xdg_shell.h @@ -3,10 +3,10 @@ #include +#include "libds/output.h" #include "xdg-shell-server-protocol.h" #include "surface.h" -#include "libds/output.h" enum ds_xdg_surface_role { diff --git a/src/libds/xdg_shell/xdg_surface.c b/src/libds/xdg_shell/xdg_surface.c index 523438d..1e1654e 100644 --- a/src/libds/xdg_shell/xdg_surface.c +++ b/src/libds/xdg_shell/xdg_surface.c @@ -1,10 +1,12 @@ #include #include -#include "xdg_shell.h" #include "libds/log.h" +#include "xdg_shell.h" + static const struct xdg_surface_interface xdg_surface_impl; + static void xdg_surface_handle_surface_destroy(struct wl_listener *listener, void *data); static void xdg_surface_handle_surface_commit(struct wl_listener *listener, diff --git a/src/libds/xdg_shell/xdg_toplevel.c b/src/libds/xdg_shell/xdg_toplevel.c index 8e78fe7..2a1e6d7 100644 --- a/src/libds/xdg_shell/xdg_toplevel.c +++ b/src/libds/xdg_shell/xdg_toplevel.c @@ -4,7 +4,8 @@ #include "xdg_shell.h" -const struct ds_surface_role xdg_toplevel_surface_role = { +static const struct ds_surface_role xdg_toplevel_surface_role = +{ .name = "xdg_toplevel", .commit = handle_xdg_surface_commit, }; @@ -17,9 +18,8 @@ void create_xdg_toplevel(struct ds_xdg_surface *surface, uint32_t id) { if (!ds_surface_set_role(surface->ds_surface, &xdg_toplevel_surface_role, - surface, surface->resource, XDG_WM_BASE_ERROR_ROLE)) { + surface, surface->resource, XDG_WM_BASE_ERROR_ROLE)) return; - } if (surface->role != DS_XDG_SURFACE_ROLE_NONE) { wl_resource_post_error(surface->resource, @@ -81,6 +81,7 @@ send_xdg_toplevel_configure(struct ds_xdg_surface *surface, struct ds_xdg_surface_configure *configure) { struct wl_array states; + uint32_t width, height; configure->toplevel_configure = malloc(sizeof *configure->toplevel_configure); @@ -125,8 +126,8 @@ send_xdg_toplevel_configure(struct ds_xdg_surface *surface, // TODO } - uint32_t width = surface->toplevel->scheduled.width; - uint32_t height = surface->toplevel->scheduled.height; + width = surface->toplevel->scheduled.width; + height = surface->toplevel->scheduled.height; xdg_toplevel_send_configure(surface->toplevel->resource, width, height, &states); @@ -297,7 +298,8 @@ xdg_toplevel_handle_set_minimized(struct wl_client *client, wl_signal_emit(&surface->toplevel->events.request_maximize, surface); } -static const struct xdg_toplevel_interface xdg_toplevel_impl = { +static const struct xdg_toplevel_interface xdg_toplevel_impl = +{ xdg_toplevel_handle_destroy, xdg_toplevel_handle_set_parent, xdg_toplevel_handle_set_title, -- 2.7.4 From 134c82c3b09f6878f8ec938a6d00d30417d2158e Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 4 Mar 2022 14:49:34 +0900 Subject: [PATCH 04/16] Remove too noisy logs Change-Id: I4144747488e21d8116e28bbb6b699a79812513ff --- src/libds/backend/tdm/output.c | 2 -- src/libds/backend/wayland/output.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/libds/backend/tdm/output.c b/src/libds/backend/tdm/output.c index 958b8ce..5148853 100644 --- a/src/libds/backend/tdm/output.c +++ b/src/libds/backend/tdm/output.c @@ -197,8 +197,6 @@ output_iface_commit(struct ds_output *ds_output) } } - ds_dbg("Swap Buffer!!!!!"); - return true; } diff --git a/src/libds/backend/wayland/output.c b/src/libds/backend/wayland/output.c index bc18875..1966a97 100644 --- a/src/libds/backend/wayland/output.c +++ b/src/libds/backend/wayland/output.c @@ -257,8 +257,6 @@ wl_output_iface_commit(struct ds_output *ds_output) wl_surface_attach(output->surface, buffer->wl_buffer, 0, 0); wl_surface_damage_buffer(output->surface, 0, 0, INT32_MAX, INT32_MAX); wl_surface_commit(output->surface); - - ds_dbg("Swap Buffer!!!!!"); } wl_display_flush(output->backend->server.display); -- 2.7.4 From e6a61d925caab5245ce6278eb0d183d3423a49ad Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 4 Mar 2022 16:27:16 +0900 Subject: [PATCH 05/16] output: Add ds_output_enable/disable APIs Change-Id: Idd7c1c7770b136bf240adbe34214101558aa31fe --- include/libds/interfaces/output.h | 2 ++ include/libds/output.h | 6 ++++++ src/libds/output.c | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/libds/interfaces/output.h b/include/libds/interfaces/output.h index 9b95db1..6fb2909 100644 --- a/include/libds/interfaces/output.h +++ b/include/libds/interfaces/output.h @@ -60,6 +60,8 @@ struct ds_output struct wl_signal frame; struct wl_signal commit; } events; + + bool enabled; }; void diff --git a/include/libds/output.h b/include/libds/output.h index c7ee476..cae9f7f 100644 --- a/include/libds/output.h +++ b/include/libds/output.h @@ -20,6 +20,12 @@ struct ds_output_mode { void ds_output_destroy(struct ds_output *output); +void +ds_output_enable(struct ds_output *output); + +void +ds_output_disable(struct ds_output *output); + bool ds_output_commit(struct ds_output *output); diff --git a/src/libds/output.c b/src/libds/output.c index 4f67056..bc286f7 100644 --- a/src/libds/output.c +++ b/src/libds/output.c @@ -7,6 +7,7 @@ static void output_handle_display_destroy(struct wl_listener *listener, void *data); +static void output_enable(struct ds_output *output, bool enable); static void output_state_clear(struct ds_output_state *state); static void output_state_clear_buffer(struct ds_output_state *state); @@ -43,6 +44,18 @@ ds_output_destroy(struct ds_output *output) free(output); } +void +ds_output_enable(struct ds_output *output) +{ + output_enable(output, true); +} + +void +ds_output_disable(struct ds_output *output) +{ + output_enable(output, false); +} + WL_EXPORT bool ds_output_commit(struct ds_output *output) { @@ -147,3 +160,15 @@ output_state_clear_buffer(struct ds_output_state *state) state->committed &= ~DS_OUTPUT_STATE_BUFFER; } + +static void +output_enable(struct ds_output *output, bool enable) +{ + if (output->enabled == enable) { + output->pending.committed &= ~DS_OUTPUT_STATE_ENABLED; + return; + } + + output->pending.committed |= DS_OUTPUT_STATE_ENABLED; + output->pending.enabled = enable; +} -- 2.7.4 From b84962f297e9ca995ebbb14266ec31672821eaba Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Tue, 8 Mar 2022 16:21:28 +0900 Subject: [PATCH 06/16] Build 'include' subdir after 'src' A variable 'features' referred from 'include' subdir is set during build of 'src'. Change-Id: Idd3db7a8384b6450fddb8173d9ec8cf4c358a42f --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index db1f43c..0e4e5c0 100644 --- a/meson.build +++ b/meson.build @@ -30,8 +30,8 @@ features = { 'tbm-allocator': false, } -subdir('include') subdir('src') +subdir('include') configure_file(output: 'config.h', install: false, configuration: cdata) -- 2.7.4 From 014278c3fb19ac4c21a074ad1f745bd1595b3359 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 16 Mar 2022 11:43:49 +0900 Subject: [PATCH 07/16] Add directories for tizen features Change-Id: Ie629354a2c689293b678cc9cc4d22227a5068a94 --- include/{libds => libds-tizen}/allocator/tbm.h | 4 +-- include/{libds => libds-tizen}/backend/tdm.h | 4 +-- include/meson.build | 16 +++++------- meson.build | 7 ------ meson_options.txt | 2 +- packaging/libds.spec | 25 +++++++++++++++--- src/examples/meson.build | 4 ++- src/examples/tdm-backend.c | 4 +-- src/examples/tinyds-tdm.c | 4 +-- src/libds-tizen/allocator/meson.build | 2 ++ src/{libds => libds-tizen}/allocator/tbm.c | 0 src/libds-tizen/backend/meson.build | 1 + src/{libds => libds-tizen}/backend/tdm/backend.c | 0 src/libds-tizen/backend/tdm/meson.build | 12 +++++++++ src/{libds => libds-tizen}/backend/tdm/output.c | 2 +- src/{libds => libds-tizen}/backend/tdm/tdm.h | 4 +-- src/libds-tizen/meson.build | 29 +++++++++++++++++++++ src/libds/allocator/meson.build | 11 -------- src/libds/backend/meson.build | 14 ----------- src/libds/backend/tdm/meson.build | 32 ------------------------ src/libds/meson.build | 7 ------ src/meson.build | 3 +++ 22 files changed, 90 insertions(+), 97 deletions(-) rename include/{libds => libds-tizen}/allocator/tbm.h (76%) rename include/{libds => libds-tizen}/backend/tdm.h (72%) create mode 100644 src/libds-tizen/allocator/meson.build rename src/{libds => libds-tizen}/allocator/tbm.c (100%) create mode 100644 src/libds-tizen/backend/meson.build rename src/{libds => libds-tizen}/backend/tdm/backend.c (100%) create mode 100644 src/libds-tizen/backend/tdm/meson.build rename src/{libds => libds-tizen}/backend/tdm/output.c (99%) rename src/{libds => libds-tizen}/backend/tdm/tdm.h (95%) create mode 100644 src/libds-tizen/meson.build delete mode 100644 src/libds/backend/tdm/meson.build diff --git a/include/libds/allocator/tbm.h b/include/libds-tizen/allocator/tbm.h similarity index 76% rename from include/libds/allocator/tbm.h rename to include/libds-tizen/allocator/tbm.h index c02aee3..3febb10 100644 --- a/include/libds/allocator/tbm.h +++ b/include/libds-tizen/allocator/tbm.h @@ -1,5 +1,5 @@ -#ifndef LIBDS_ALLOCATOR_TBM_H -#define LIBDS_ALLOCATOR_TBM_H +#ifndef LIBDS_TIZEN_ALLOCATOR_TBM_H +#define LIBDS_TIZEN_ALLOCATOR_TBM_H #include diff --git a/include/libds/backend/tdm.h b/include/libds-tizen/backend/tdm.h similarity index 72% rename from include/libds/backend/tdm.h rename to include/libds-tizen/backend/tdm.h index e697413..d2785b2 100644 --- a/include/libds/backend/tdm.h +++ b/include/libds-tizen/backend/tdm.h @@ -1,5 +1,5 @@ -#ifndef LIBDS_BACKEND_TDM_H -#define LIBDS_BACKEND_TDM_H +#ifndef LIBDS_TIZEN_BACKEND_TDM_H +#define LIBDS_TIZEN_BACKEND_TDM_H #include diff --git a/include/meson.build b/include/meson.build index f273424..0975c5d 100644 --- a/include/meson.build +++ b/include/meson.build @@ -1,13 +1,9 @@ -exclude_files = [] -if not features.get('tdm-backend') - exclude_files += 'backend/tdm.h' -endif - -if not features.get('tbm-allocator') - exclude_files += 'allocator/tbm.h' -endif - install_subdir('libds', install_dir: get_option('includedir'), - exclude_files: exclude_files, ) + +if get_option('tizen') + install_subdir('libds-tizen', + install_dir: get_option('includedir'), + ) +endif diff --git a/meson.build b/meson.build index 0e4e5c0..d3d2df0 100644 --- a/meson.build +++ b/meson.build @@ -25,14 +25,7 @@ cdata.set('LIBDS_VERSION_MAJOR', libds_version_major) cdata.set('LIBDS_VERSION_MINOR', libds_version_minor) cdata.set('LIBDS_VERSION_PATCH', libds_version_patch) -features = { - 'tdm-backend': false, - 'tbm-allocator': false, -} - subdir('src') subdir('include') configure_file(output: 'config.h', install: false, configuration: cdata) - -summary(features, bool_yn: true) diff --git a/meson_options.txt b/meson_options.txt index 02af9b0..6ef6c8e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1 @@ -option('backends', type: 'array', choices: ['auto', 'tdm'], value: ['auto'], description: 'Select built-in backends') +option('tizen', type: 'boolean', value: false, description: 'Build Tizen features') diff --git a/packaging/libds.spec b/packaging/libds.spec index bd38de7..879a87d 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -30,6 +30,12 @@ Requires: %{name} = %{version}-%{release} %description devel Development package of Wayland Compositor Library +%package tizen-devel +Summary: Wayland Compositor development package on Tizen + +%description tizen-devel +Wayland Compositor development library for Tizen platform + %prep %setup -q cp %{SOURCE1001} . @@ -39,7 +45,8 @@ meson setup \ --prefix /usr \ --libdir %{_libdir} \ --bindir %{_bindir} \ - builddir + builddir \ + -Dtizen=true ninja -C builddir all %install @@ -56,7 +63,19 @@ ninja -C builddir install %manifest %{name}.manifest %defattr(-,root,root,-) %license LICENSE -%{_includedir}/* +%{_includedir}/libds/* %{_libdir}/pkgconfig/libds.pc %{_libdir}/libds.so -%{_bindir}/* +%{_bindir}/wl-backend +%{_bindir}/tinyds + +%files tizen-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/* +%{_libdir}/pkgconfig/libds-tizen.pc +%{_libdir}/libds-tizen.so +%{_bindir}/tdm-backend +%{_bindir}/tinyds-tdm +%{_bindir}/ds-simple-tbm diff --git a/src/examples/meson.build b/src/examples/meson.build index 193b4a5..f95bd50 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -23,7 +23,9 @@ executable('tinyds', install : true ) -if features.get('tdm-backend') +if get_option('tizen') + common_deps += dep_libds_tizen + executable('tdm-backend', 'tdm-backend.c', dependencies: common_deps, diff --git a/src/examples/tdm-backend.c b/src/examples/tdm-backend.c index ee39f06..ba3fecb 100644 --- a/src/examples/tdm-backend.c +++ b/src/examples/tdm-backend.c @@ -8,10 +8,10 @@ #include #include #include -#include -#include #include #include +#include +#include #define WIDTH 1280 #define HEIGHT 720 diff --git a/src/examples/tinyds-tdm.c b/src/examples/tinyds-tdm.c index 2c91a66..143d53e 100644 --- a/src/examples/tinyds-tdm.c +++ b/src/examples/tinyds-tdm.c @@ -14,11 +14,11 @@ #include #include #include -#include -#include #include #include #include +#include +#include #define TINYDS_UNUSED __attribute__((unused)) diff --git a/src/libds-tizen/allocator/meson.build b/src/libds-tizen/allocator/meson.build new file mode 100644 index 0000000..fe869bd --- /dev/null +++ b/src/libds-tizen/allocator/meson.build @@ -0,0 +1,2 @@ +libds_tizen_files += files('tbm.c') +libds_tizen_deps += dependency('libtbm', required: true) diff --git a/src/libds/allocator/tbm.c b/src/libds-tizen/allocator/tbm.c similarity index 100% rename from src/libds/allocator/tbm.c rename to src/libds-tizen/allocator/tbm.c diff --git a/src/libds-tizen/backend/meson.build b/src/libds-tizen/backend/meson.build new file mode 100644 index 0000000..8a05e13 --- /dev/null +++ b/src/libds-tizen/backend/meson.build @@ -0,0 +1 @@ +subdir('tdm') diff --git a/src/libds/backend/tdm/backend.c b/src/libds-tizen/backend/tdm/backend.c similarity index 100% rename from src/libds/backend/tdm/backend.c rename to src/libds-tizen/backend/tdm/backend.c diff --git a/src/libds-tizen/backend/tdm/meson.build b/src/libds-tizen/backend/tdm/meson.build new file mode 100644 index 0000000..39ffceb --- /dev/null +++ b/src/libds-tizen/backend/tdm/meson.build @@ -0,0 +1,12 @@ +libds_tizen_files += files( + 'backend.c', + 'output.c', +) + +libtdm = dependency('libtdm', required: true) +libtbm = dependency('libtbm', required: true) + +libds_tizen_deps += [ + libtdm, + libtbm +] diff --git a/src/libds/backend/tdm/output.c b/src/libds-tizen/backend/tdm/output.c similarity index 99% rename from src/libds/backend/tdm/output.c rename to src/libds-tizen/backend/tdm/output.c index 5148853..f6b6250 100644 --- a/src/libds/backend/tdm/output.c +++ b/src/libds-tizen/backend/tdm/output.c @@ -4,7 +4,7 @@ #include #include "libds/log.h" -#include "libds/allocator/tbm.h" +#include "libds-tizen/allocator/tbm.h" #include "tdm.h" diff --git a/src/libds/backend/tdm/tdm.h b/src/libds-tizen/backend/tdm/tdm.h similarity index 95% rename from src/libds/backend/tdm/tdm.h rename to src/libds-tizen/backend/tdm/tdm.h index 1c80ef9..275089c 100644 --- a/src/libds/backend/tdm/tdm.h +++ b/src/libds-tizen/backend/tdm/tdm.h @@ -1,5 +1,5 @@ -#ifndef DS_BACKEND_TDM_H -#define DS_BACKEND_TDM_H +#ifndef DS_TIZEN_BACKEND_TDM_H +#define DS_TIZEN_BACKEND_TDM_H #include diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build new file mode 100644 index 0000000..e9ca734 --- /dev/null +++ b/src/libds-tizen/meson.build @@ -0,0 +1,29 @@ +libds_tizen_files = [] + +libds_tizen_deps = [ + dep_libds, +] + +subdir('allocator') +subdir('backend') + +lib_libds_tizen = shared_library('ds-tizen', libds_tizen_files, + dependencies: libds_tizen_deps, + include_directories: [ common_inc, include_directories('.') ], + version: meson.project_version(), + install: true +) + +dep_libds_tizen = declare_dependency( + link_with: lib_libds_tizen, + dependencies: libds_tizen_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen, + version: meson.project_version(), + filebase: 'libds-tizen', + name: 'libds-tizen', + description: 'extension of libds for tizen platform', +) diff --git a/src/libds/allocator/meson.build b/src/libds/allocator/meson.build index 361f96e..173c219 100644 --- a/src/libds/allocator/meson.build +++ b/src/libds/allocator/meson.build @@ -1,12 +1 @@ libds_files += files('shm.c') - -libtbm = dependency( - 'libtbm', - required: false, - not_found_message: 'Required for TBM allocator support.' -) -if libtbm.found() - libds_files += files('tbm.c') - libds_deps += libtbm - features += { 'tbm-allocator': true } -endif diff --git a/src/libds/backend/meson.build b/src/libds/backend/meson.build index b1fff87..895ffca 100644 --- a/src/libds/backend/meson.build +++ b/src/libds/backend/meson.build @@ -1,15 +1 @@ -all_backends = ['tdm'] -backends = get_option('backends') -if 'auto' in backends and get_option('auto_features').enabled() - backends = all_backends -elif 'auto' in backends and get_option('auto_features').disabled() - backends = [] -endif - -foreach backend : all_backends - if backend in backends or 'auto' in backends - subdir(backend) - endif -endforeach - subdir('wayland') diff --git a/src/libds/backend/tdm/meson.build b/src/libds/backend/tdm/meson.build deleted file mode 100644 index 82eb165..0000000 --- a/src/libds/backend/tdm/meson.build +++ /dev/null @@ -1,32 +0,0 @@ -msg = ['Required for TDM backend support.'] -if 'tdm' in backends - msg += 'Install "libtdm" and "libtbm", or disable the tdm backend' -endif - -libtdm = dependency( - 'libtdm', - required: 'tdm' in backends, - not_found_message: '\n'.join(msg) -) - -libtbm = dependency( - 'libtbm', - required: 'tdm' in backends, - not_found_message: '\n'.join(msg) -) - -if not libtdm.found() or not libtbm.found() - subdir_done() -endif - -libds_files += files( - 'backend.c', - 'output.c', -) - -libds_deps += [ - libtdm, - libtbm -] - -features += { 'tdm-backend': true } diff --git a/src/libds/meson.build b/src/libds/meson.build index ed8c95f..50f7962 100644 --- a/src/libds/meson.build +++ b/src/libds/meson.build @@ -68,16 +68,10 @@ lib_libds = shared_library('ds', libds_files, install: true ) -ds_vars = {} -foreach name, have : features - ds_vars += { 'have_' + name.underscorify(): have.to_string() } -endforeach - dep_libds = declare_dependency( link_with: lib_libds, dependencies: libds_deps, include_directories: [ common_inc, include_directories('.') ], - variables: ds_vars, ) pkgconfig = import('pkgconfig') @@ -86,5 +80,4 @@ pkgconfig.generate(lib_libds, filebase: meson.project_name(), name: meson.project_name(), description: 'Wayland compositor library', - variables: ds_vars, ) diff --git a/src/meson.build b/src/meson.build index 774c7eb..d739bfe 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,6 +11,9 @@ wayland_scanner = find_program( ) subdir('libds') +if get_option('tizen') + subdir('libds-tizen') +endif subdir('tests') subdir('examples') subdir('clients') -- 2.7.4 From a8b54995b578abd5547803c605c0d430be775df6 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 16 Mar 2022 13:18:21 +0900 Subject: [PATCH 08/16] libds-tizen: Add ds_tdm_buffer_queue A ds_tdm_buffer_queue is a buffer queue that is able to be acquired from ds_tdm_output. A ds_tdm_buffer_queue provides a handle of native queue to a user and the user may pass it to a renderer. The renderer then should think of native queue as tbm_surface_queue_h. With the tbm_surface_queue_h, the renderer may dequeue a surface from it and draw on the dequeued buffer. After finish drawing on the buffer, the renderer should enqueue it to the tbm_surface_queue_h. As soon as the renderer enqueues buffer to the tbm_surface_queue_h, the user can recieve a notification that the buffer can be acquired from the ds_tbm_buffer_queue using ds_tdm_buffer_queue_add_acquirable_listener(). Then user may acquire a buffer from the ds_tdm_buffer_queue and attach it to a ds_output. Note that although the renderer may enqueue a buffer on different thread from the thread working on libds, but libds will call a callback function which is registered using ds_tdm_buffer_queue_add_acquirable_listener() on the thread working on libds. Change-Id: Ib50d2f11cdb27c0aa34b6beeecc73f012032c685 --- include/libds-tizen/backend/tdm.h | 21 ++ src/libds-tizen/backend/tdm/meson.build | 1 + src/libds-tizen/backend/tdm/output.c | 107 +++++++-- src/libds-tizen/backend/tdm/tdm.h | 5 +- src/libds-tizen/backend/tdm/tdm_buffer_queue.c | 311 +++++++++++++++++++++++++ src/libds-tizen/backend/tdm/tdm_buffer_queue.h | 45 ++++ 6 files changed, 464 insertions(+), 26 deletions(-) create mode 100644 src/libds-tizen/backend/tdm/tdm_buffer_queue.c create mode 100644 src/libds-tizen/backend/tdm/tdm_buffer_queue.h diff --git a/include/libds-tizen/backend/tdm.h b/include/libds-tizen/backend/tdm.h index d2785b2..8c5c605 100644 --- a/include/libds-tizen/backend/tdm.h +++ b/include/libds-tizen/backend/tdm.h @@ -2,14 +2,35 @@ #define LIBDS_TIZEN_BACKEND_TDM_H #include +#include #ifdef __cplusplus extern "C" { #endif +struct ds_tdm_output; + +struct ds_tdm_buffer_queue; + struct ds_backend * ds_tdm_backend_create(struct wl_display *display); +struct ds_tdm_output * +ds_tdm_output_from_output(struct ds_output *ds_output); + +struct ds_tdm_buffer_queue * +ds_tdm_output_get_buffer_queue(struct ds_tdm_output *output); + +void * +ds_tdm_buffer_queue_get_native_queue(struct ds_tdm_buffer_queue *queue); + +struct ds_buffer * +ds_tdm_buffer_queue_acquire(struct ds_tdm_buffer_queue *queue); + +void +ds_tdm_buffer_queue_add_acquirable_listener(struct ds_tdm_buffer_queue *queue, + struct wl_listener *listener); + #ifdef __cplusplus } #endif diff --git a/src/libds-tizen/backend/tdm/meson.build b/src/libds-tizen/backend/tdm/meson.build index 39ffceb..932559f 100644 --- a/src/libds-tizen/backend/tdm/meson.build +++ b/src/libds-tizen/backend/tdm/meson.build @@ -1,6 +1,7 @@ libds_tizen_files += files( 'backend.c', 'output.c', + 'tdm_buffer_queue.c', ) libtdm = dependency('libtdm', required: true) diff --git a/src/libds-tizen/backend/tdm/output.c b/src/libds-tizen/backend/tdm/output.c index f6b6250..10b9666 100644 --- a/src/libds-tizen/backend/tdm/output.c +++ b/src/libds-tizen/backend/tdm/output.c @@ -7,6 +7,7 @@ #include "libds-tizen/allocator/tbm.h" #include "tdm.h" +#include "tdm_buffer_queue.h" static const struct ds_output_interface tdm_output_iface; static bool output_init_modes(struct ds_tdm_output *output); @@ -17,6 +18,32 @@ static bool output_set_pending_fb(struct ds_tdm_output *output, struct ds_buffer *ds_buffer); static bool output_hwc_commit(struct ds_tdm_output *output); +WL_EXPORT struct ds_tdm_output * +ds_tdm_output_from_output(struct ds_output *ds_output) +{ + if (ds_output->iface != &tdm_output_iface) { + ds_err("Given ds_output is not for ds_tdm_output"); + return NULL; + } + + return (struct ds_tdm_output *)ds_output; +} + +WL_EXPORT struct ds_tdm_buffer_queue * +ds_tdm_output_get_buffer_queue(struct ds_tdm_output *output) +{ + if (output->queue) + return output->queue; + + output->queue = create_buffer_queue(output); + if (!output->queue) { + ds_err("Could not create tbm_queue with output(%p)", output); + return NULL; + } + + return output->queue; +} + struct ds_tdm_output * create_tdm_output(struct ds_tdm_backend *tdm, tdm_output *tdm_output) { @@ -89,12 +116,25 @@ destroy_tdm_buffer(struct ds_tdm_buffer *buffer) if (buffer == NULL) return; + if (!buffer->released) + wl_list_remove(&buffer->buffer_release.link); + wl_list_remove(&buffer->buffer_destroy.link); wl_list_remove(&buffer->link); free(buffer); } static void +buffer_handle_buffer_release(struct wl_listener *listener, void *data) +{ + struct ds_tdm_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + wl_list_remove(&buffer->buffer_release.link); + buffer->released = true; +} + +static void buffer_handle_buffer_destroy(struct wl_listener *listener, void *data) { struct ds_tdm_buffer *buffer; @@ -120,7 +160,7 @@ create_tdm_buffer(struct ds_tdm_backend *backend, struct ds_buffer *ds_buffer) return NULL; buffer->surface = surface; - buffer->buffer = ds_buffer_lock(ds_buffer); + buffer->buffer = ds_buffer; wl_list_insert(&backend->buffers, &buffer->link); buffer->buffer_destroy.notify = buffer_handle_buffer_destroy; @@ -137,37 +177,38 @@ get_or_create_tdm_buffer(struct ds_tdm_backend *backend, wl_list_for_each(buffer, &backend->buffers, link) { if (buffer->buffer == ds_buffer && buffer->released) { - buffer->released = false; - ds_buffer_lock(buffer->buffer); - return buffer; + goto out; } } - return create_tdm_buffer(backend, ds_buffer); -} + buffer = create_tdm_buffer(backend, ds_buffer); -static void -tdm_buffer_release(struct ds_tdm_buffer *buffer) -{ - buffer->released = true; - ds_buffer_unlock(buffer->buffer); +out: + buffer->released = false; + + buffer->buffer_release.notify = buffer_handle_buffer_release; + ds_buffer_add_release_listener(ds_buffer, &buffer->buffer_release); + + ds_buffer_lock(buffer->buffer); + + return buffer; } static void output_update_front_buffer(struct ds_tdm_output *output) { if (output->front_buffer) - tdm_buffer_release(output->front_buffer); + ds_buffer_unlock(output->front_buffer); output->front_buffer = output->back_buffer; output->back_buffer = NULL; } static void output_attach_back_buffer(struct ds_tdm_output *output, - struct ds_tdm_buffer *buffer) + struct ds_buffer *buffer) { if (output->back_buffer) - tdm_buffer_release(output->back_buffer); + ds_buffer_unlock(output->back_buffer); output->back_buffer = buffer; } @@ -192,9 +233,8 @@ output_iface_commit(struct ds_output *ds_output) if (!output_hwc_commit(output)) { ds_err("Could not commit tdm output"); - if (output->back_buffer) { - tdm_buffer_release(output->back_buffer); - } + if (output->back_buffer) + ds_buffer_unlock(output->back_buffer); } return true; @@ -217,10 +257,13 @@ output_destroy(struct ds_tdm_output *output) } if (output->back_buffer) - ds_buffer_unlock(output->back_buffer->buffer); + ds_buffer_unlock(output->back_buffer); if (output->front_buffer) - ds_buffer_unlock(output->front_buffer->buffer); + ds_buffer_unlock(output->front_buffer); + + if (output->queue) + buffer_queue_destroy(output->queue); free(output); } @@ -306,24 +349,38 @@ static bool output_set_pending_fb(struct ds_tdm_output *output, struct ds_buffer *ds_buffer) { + struct ds_tdm_queue_buffer *queue_buffer; struct ds_tdm_buffer *buffer; + tbm_surface_h surface = NULL; tdm_region fb_damage; tdm_error err; - buffer = get_or_create_tdm_buffer(output->backend, ds_buffer); - if (!buffer) - return false; + if (output->queue) { + queue_buffer = buffer_queue_find_buffer(output->queue, ds_buffer); + if (queue_buffer) { + ds_buffer_lock(ds_buffer); + surface = queue_buffer->surface; + } + } + + if (!surface) { + buffer = get_or_create_tdm_buffer(output->backend, ds_buffer); + if (!buffer) + return false; + + surface = buffer->surface; + } memset(&fb_damage, 0, sizeof(fb_damage)); err = tdm_hwc_set_client_target_buffer(output->tdm.hwc, - buffer->surface, fb_damage); + surface, fb_damage); if (err != TDM_ERROR_NONE) { ds_err("Could not set hwc client target buffer"); - ds_buffer_unlock(buffer->buffer); + ds_buffer_unlock(ds_buffer); return false; } - output_attach_back_buffer(output, buffer); + output_attach_back_buffer(output, ds_buffer); return true; } diff --git a/src/libds-tizen/backend/tdm/tdm.h b/src/libds-tizen/backend/tdm/tdm.h index 275089c..f19483f 100644 --- a/src/libds-tizen/backend/tdm/tdm.h +++ b/src/libds-tizen/backend/tdm/tdm.h @@ -40,7 +40,8 @@ struct ds_tdm_output struct ds_output base; struct ds_tdm_backend *backend; - struct ds_tdm_buffer *front_buffer, *back_buffer; + struct ds_tdm_buffer_queue *queue; + struct ds_buffer *front_buffer, *back_buffer; struct { tdm_output *output; @@ -57,6 +58,8 @@ struct ds_tdm_buffer struct ds_buffer *buffer; tbm_surface_h surface; struct wl_list link; // ds_wl_backend.buffers + + struct wl_listener buffer_release; struct wl_listener buffer_destroy; bool released; diff --git a/src/libds-tizen/backend/tdm/tdm_buffer_queue.c b/src/libds-tizen/backend/tdm/tdm_buffer_queue.c new file mode 100644 index 0000000..7a2a1aa --- /dev/null +++ b/src/libds-tizen/backend/tdm/tdm_buffer_queue.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include + +#include "libds/log.h" +#include "libds/interfaces/buffer.h" + +#include "tdm.h" +#include "tdm_buffer_queue.h" + +static void +buffer_queue_handle_acquirable(tbm_surface_queue_h surface_queue, + void *data); +static struct ds_tdm_queue_buffer * +create_queue_buffer(struct ds_tdm_buffer_queue *queue, + tbm_surface_h surface); +static void queue_buffer_destroy(struct ds_tdm_queue_buffer *buffer); +static void queue_buffer_drop(struct ds_tdm_queue_buffer *buffer); +static struct ds_buffer * +queue_buffer_acquire(struct ds_tdm_queue_buffer *buffer); +static int buffer_queue_handle_acquirable_efd(int fd, uint32_t mask, + void *data); + +WL_EXPORT void * +ds_tdm_buffer_queue_get_native_queue(struct ds_tdm_buffer_queue *queue) +{ + return (void *)queue->tbm_surface_queue; +} + +WL_EXPORT struct ds_buffer * +ds_tdm_buffer_queue_acquire(struct ds_tdm_buffer_queue *queue) +{ + struct ds_tdm_queue_buffer *buffer; + tbm_surface_h surface; + tbm_surface_queue_error_e err; + + if (!tbm_surface_queue_can_acquire(queue->tbm_surface_queue, 0)) + return NULL; + + err = tbm_surface_queue_acquire(queue->tbm_surface_queue, &surface); + if (err != TBM_SURFACE_QUEUE_ERROR_NONE || + surface == NULL) { + ds_err("Could not acquire tbm_surface from queue(%p)", queue); + return NULL; + } + + wl_list_for_each(buffer, &queue->buffers, link) { + if (buffer->surface == surface) + return queue_buffer_acquire(buffer); + } + + buffer = create_queue_buffer(queue, surface); + if (!buffer) { + ds_err("Could not create tbm_queue_buffer with queue(%p)", queue); + return NULL; + } + + wl_list_insert(&queue->buffers, &buffer->link); + + return queue_buffer_acquire(buffer); +} + +WL_EXPORT void +ds_tdm_buffer_queue_add_acquirable_listener(struct ds_tdm_buffer_queue *queue, + struct wl_listener *listener) +{ + wl_signal_add(&queue->events.acquirable, listener); +} + +struct ds_tdm_buffer_queue * +create_buffer_queue(struct ds_tdm_output *output) +{ + struct ds_tdm_buffer_queue *queue; + tdm_error err; + + queue = calloc(1, sizeof *queue); + if (!queue) + return NULL; + + wl_list_init(&queue->buffers); + + wl_signal_init(&queue->events.acquirable); + + queue->tbm_surface_queue = + tdm_hwc_get_client_target_buffer_queue(output->tdm.hwc, &err); + if (err != TDM_ERROR_NONE || + queue->tbm_surface_queue == NULL) { + ds_err("Could not get target buffer queue: err(%d)", err); + free(queue); + return NULL; + } + + tbm_surface_queue_reset(queue->tbm_surface_queue, + output->base.pending.mode->width, + output->base.pending.mode->height, + tbm_surface_queue_get_format(queue->tbm_surface_queue)); + + /* The callback function for tbm_surface_queue_add_acquirable_cb() may be + * called on different thread. This eventfd is to emit a signal of + * events.acquirable on the thread getting this buffer queue. */ + queue->acquirable_efd = eventfd(0, EFD_NONBLOCK); + if (queue->acquirable_efd < 0) { + ds_log_errno(DS_ERR, + "Could not create eventfd for acquirable callback"); + free(queue); + return NULL; + } + + queue->acquirable_source = wl_event_loop_add_fd( + wl_display_get_event_loop(output->backend->wl_display), + queue->acquirable_efd, + WL_EVENT_READABLE, + buffer_queue_handle_acquirable_efd, + queue); + + tbm_surface_queue_add_acquirable_cb(queue->tbm_surface_queue, + buffer_queue_handle_acquirable, (void *)queue); + + return queue; +} + +void +buffer_queue_destroy(struct ds_tdm_buffer_queue *queue) +{ + struct ds_tdm_queue_buffer *buffer, *buffer_tmp; + + wl_list_for_each_safe(buffer, buffer_tmp, &queue->buffers, link) + queue_buffer_drop(buffer); + + wl_event_source_remove(queue->acquirable_source); + close(queue->acquirable_efd); + tbm_surface_queue_destroy(queue->tbm_surface_queue); + free(queue); +} + +struct ds_tdm_queue_buffer * +buffer_queue_find_buffer(struct ds_tdm_buffer_queue *queue, + struct ds_buffer *ds_buffer) +{ + struct ds_tdm_queue_buffer *buffer; + + wl_list_for_each(buffer, &queue->buffers, link) { + if (&buffer->base == ds_buffer) + return buffer; + } + + return NULL; +} + +static void +buffer_queue_handle_acquirable(tbm_surface_queue_h surface_queue, void *data) +{ + struct ds_tdm_buffer_queue *queue = data; + uint64_t acquirable = 1; + int ret; + + ret = write(queue->acquirable_efd, &acquirable, sizeof(acquirable)); + if (ret < 0) + ds_log_errno(DS_ERR, "Could not write eventfd for acquirable buffer"); +} + +static const struct ds_buffer_interface queue_buffer_iface; + +static struct ds_tdm_queue_buffer * +create_queue_buffer(struct ds_tdm_buffer_queue *queue, tbm_surface_h surface) +{ + struct ds_tdm_queue_buffer *buffer; + + buffer = calloc(1, sizeof *buffer); + if (!buffer) + return NULL; + + ds_buffer_init(&buffer->base, &queue_buffer_iface, + tbm_surface_get_width(surface), + tbm_surface_get_height(surface)); + + buffer->queue = queue; + buffer->surface = surface; + + return buffer; +} + +static void +queue_buffer_destroy(struct ds_tdm_queue_buffer *buffer) +{ + free(buffer); +} + +static struct ds_tdm_queue_buffer * +queue_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + assert(ds_buffer->iface == &queue_buffer_iface); + return (struct ds_tdm_queue_buffer *)ds_buffer; +} + +static void +queue_buffer_iface_destroy(struct ds_buffer *ds_buffer) +{ + struct ds_tdm_queue_buffer *buffer; + + buffer = queue_buffer_from_buffer(ds_buffer); + queue_buffer_destroy(buffer); +} + +static bool +queue_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer, + uint32_t flags, void **data, uint32_t *format, size_t *stride) +{ + struct ds_tdm_queue_buffer *buffer; + tbm_surface_info_s info; + int tbm_access_flags = 0; + int ret; + + buffer = queue_buffer_from_buffer(ds_buffer); + + if (!buffer->surface) { + ds_err("No tbm_surface. It's a dropped buffer(%p)", buffer); + return false; + } + + if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ) + tbm_access_flags |= TBM_OPTION_READ; + else if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE) + tbm_access_flags |= TBM_OPTION_WRITE; + + ret = tbm_surface_map(buffer->surface, tbm_access_flags, &info); + if (ret != TBM_SURFACE_ERROR_NONE) { + ds_err("Could not map tbm_surface of buffer(%p)", buffer); + return false; + } + + *data = info.planes[0].ptr; + *format = info.format; + *stride = info.planes[0].stride; + + return true; +} + +static void +queue_buffer_iface_end_data_ptr_access(struct ds_buffer *ds_buffer) +{ + struct ds_tdm_queue_buffer *buffer; + + buffer = queue_buffer_from_buffer(ds_buffer); + if (!buffer->surface) { + ds_err("No tbm_surface. It's a dropped buffer(%p)", buffer); + return; + } + + tbm_surface_unmap(buffer->surface); +} + +static const struct ds_buffer_interface queue_buffer_iface = +{ + .destroy = queue_buffer_iface_destroy, + .begin_data_ptr_access = queue_buffer_iface_begin_data_ptr_access, + .end_data_ptr_access = queue_buffer_iface_end_data_ptr_access, +}; + +static void +queue_buffer_handle_buffer_release(struct wl_listener *listener, void *data) +{ + struct ds_tdm_queue_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + + wl_list_remove(&buffer->buffer_release.link); + buffer->acquired = false; + + tbm_surface_queue_release(buffer->queue->tbm_surface_queue, + buffer->surface); +} + +static void +queue_buffer_drop(struct ds_tdm_queue_buffer *buffer) +{ + if (buffer->acquired) + wl_list_remove(&buffer->buffer_release.link); + + wl_list_remove(&buffer->link); + ds_buffer_drop(&buffer->base); + buffer->surface = NULL; +} + +static struct ds_buffer * +queue_buffer_acquire(struct ds_tdm_queue_buffer *buffer) +{ + assert(!buffer->acquired); + + buffer->acquired = true; + buffer->buffer_release.notify = queue_buffer_handle_buffer_release; + ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release); + + return ds_buffer_lock(&buffer->base); +} + +static int +buffer_queue_handle_acquirable_efd(int fd, uint32_t mask, void *data) +{ + struct ds_tdm_buffer_queue *queue = data; + uint64_t acquirable_event; + + if (read(fd, &acquirable_event, sizeof(acquirable_event)) < 0 && + errno != EAGAIN) + return -1; + + wl_signal_emit(&queue->events.acquirable, queue); + + return 0; +} diff --git a/src/libds-tizen/backend/tdm/tdm_buffer_queue.h b/src/libds-tizen/backend/tdm/tdm_buffer_queue.h new file mode 100644 index 0000000..774b7c3 --- /dev/null +++ b/src/libds-tizen/backend/tdm/tdm_buffer_queue.h @@ -0,0 +1,45 @@ +#ifndef DS_TIZEN_BACKEND_TDM_BUFFER_QUEUE_H +#define DS_TIZEN_BACKEND_TBM_BUFFER_QUEUE_H + +#include +#include + +#include "tdm.h" + +struct ds_tdm_buffer_queue +{ + tbm_surface_queue_h tbm_surface_queue; + struct wl_event_source *acquirable_source; + + struct wl_list buffers; // ds_tdm_queue_buffer.link + + struct { + struct wl_signal acquirable; + } events; + + int acquirable_efd; +}; + +struct ds_tdm_queue_buffer +{ + struct ds_buffer base; + + struct ds_tdm_output *output; + struct ds_tdm_buffer_queue *queue; + tbm_surface_h surface; + + struct wl_list link; + struct wl_listener buffer_release; + + bool acquired; +}; + +struct ds_tdm_buffer_queue *create_buffer_queue(struct ds_tdm_output *output); + +void buffer_queue_destroy(struct ds_tdm_buffer_queue *queue); + +struct ds_tdm_queue_buffer * +buffer_queue_find_buffer(struct ds_tdm_buffer_queue *queue, + struct ds_buffer *ds_buffer); + +#endif -- 2.7.4 From 142714973405f2f4743924f5b619b7d116f98f5e Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 17 Mar 2022 16:40:37 +0900 Subject: [PATCH 09/16] Add an example of using ds_tdm_buffer_queue Dependeing on the declaration of USE_TDM_BUFFER_QUEUE macro, tinyds-tdm may be run with ds_tbm_buffer_queue. Change-Id: I0e9617a6d9a18c00685fc0e25ac2a531f400e948 --- src/examples/meson.build | 3 + src/examples/pixman-helper.c | 5 +- src/examples/pixman-helper.h | 3 + src/examples/pixman-tbm-helper.c | 64 +++++++++++ src/examples/pixman-tbm-helper.h | 13 +++ src/examples/tbm-server-helper.c | 24 ++-- src/examples/tbm-server-helper.h | 6 + src/examples/tinyds-tdm-renderer.c | 187 ++++++++++++++++++++++++++++++ src/examples/tinyds-tdm-renderer.h | 48 ++++++++ src/examples/tinyds-tdm.c | 227 +++++++++++++++++++++++++++++-------- 10 files changed, 520 insertions(+), 60 deletions(-) create mode 100644 src/examples/pixman-tbm-helper.c create mode 100644 src/examples/pixman-tbm-helper.h create mode 100644 src/examples/tinyds-tdm-renderer.c create mode 100644 src/examples/tinyds-tdm-renderer.h diff --git a/src/examples/meson.build b/src/examples/meson.build index f95bd50..c60b610 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -35,8 +35,10 @@ if get_option('tizen') tinyds_tdm_files = [ 'tinyds-tdm.c', + 'tinyds-tdm-renderer.c', 'tbm-server-helper.c', 'pixman-helper.c', + 'pixman-tbm-helper.c', ] executable('tinyds-tdm', tinyds_tdm_files, @@ -46,6 +48,7 @@ if get_option('tizen') dependency('libdrm', required: true), dependency('libtbm', required: true), dependency('wayland-tbm-server', required: true), + dependency('threads', required: true), ], install_dir: libds_bindir, install : true diff --git a/src/examples/pixman-helper.c b/src/examples/pixman-helper.c index 5d42ec6..36a22e8 100644 --- a/src/examples/pixman-helper.c +++ b/src/examples/pixman-helper.c @@ -5,8 +5,6 @@ static void destroy_pixman_image(pixman_image_t *image, void *data); static uint32_t convert_drm_format_to_pixman(uint32_t fmt); -static pixman_color_t *color_rgb888(pixman_color_t *tmp, - uint8_t r, uint8_t g, uint8_t b); pixman_image_t * pixman_image_from_buffer(struct ds_buffer *buffer, @@ -37,7 +35,6 @@ pixman_image_from_buffer(struct ds_buffer *buffer, return image; } - void pixman_image_fill_color(pixman_image_t *image, uint8_t r, uint8_t g, uint8_t b) { @@ -56,7 +53,7 @@ pixman_image_fill_color(pixman_image_t *image, uint8_t r, uint8_t g, uint8_t b) pixman_image_unref(color_image); } -static pixman_color_t * +pixman_color_t * color_rgb888(pixman_color_t *tmp, uint8_t r, uint8_t g, uint8_t b) { tmp->alpha = 65535; diff --git a/src/examples/pixman-helper.h b/src/examples/pixman-helper.h index aa039ff..99ceaca 100644 --- a/src/examples/pixman-helper.h +++ b/src/examples/pixman-helper.h @@ -12,4 +12,7 @@ void pixman_image_fill_color(pixman_image_t *image, uint8_t r, uint8_t g, uint8_t b); +pixman_color_t * +color_rgb888(pixman_color_t *tmp, uint8_t r, uint8_t g, uint8_t b); + #endif diff --git a/src/examples/pixman-tbm-helper.c b/src/examples/pixman-tbm-helper.c new file mode 100644 index 0000000..710eceb --- /dev/null +++ b/src/examples/pixman-tbm-helper.c @@ -0,0 +1,64 @@ +#include + +#include "pixman-tbm-helper.h" + +static uint32_t convert_tbm_format_to_pixman(uint32_t fmt); +static void destroy_tbm_pixman_image(pixman_image_t *image, void *data); + +pixman_image_t * +pixman_image_from_tbm_surface(tbm_surface_h surface, + enum ds_buffer_data_ptr_access_flag access_flag) +{ + pixman_image_t *image; + tbm_surface_info_s info; + uint32_t format; + int tbm_access_flag = 0; + int width, height; + int ret; + + width = tbm_surface_get_width(surface); + height = tbm_surface_get_height(surface); + + if (access_flag & DS_BUFFER_DATA_PTR_ACCESS_READ) + tbm_access_flag |= TBM_OPTION_READ; + if (access_flag & DS_BUFFER_DATA_PTR_ACCESS_WRITE) + tbm_access_flag |= TBM_OPTION_WRITE; + + ret = tbm_surface_map(surface, tbm_access_flag, &info); + assert(ret == TBM_SURFACE_ERROR_NONE); + + format = convert_tbm_format_to_pixman(info.format); + image = pixman_image_create_bits(format, width, height, + (uint32_t *)info.planes[0].ptr, + info.planes[0].stride); + assert(image); + + tbm_surface_internal_ref(surface); + + pixman_image_set_destroy_function(image, + destroy_tbm_pixman_image, surface); + + return image; +} + +static void +destroy_tbm_pixman_image(pixman_image_t *image, void *data) +{ + tbm_surface_h surface = data; + + tbm_surface_unmap(surface); + tbm_surface_internal_unref(surface); +} + +static uint32_t +convert_tbm_format_to_pixman(uint32_t fmt) +{ + switch (fmt) { + case TBM_FORMAT_XRGB8888: + return PIXMAN_x8r8g8b8; + case TBM_FORMAT_ARGB8888: + return PIXMAN_a8r8g8b8; + default: + assert(0 && "not reached"); + } +} diff --git a/src/examples/pixman-tbm-helper.h b/src/examples/pixman-tbm-helper.h new file mode 100644 index 0000000..bf9bd55 --- /dev/null +++ b/src/examples/pixman-tbm-helper.h @@ -0,0 +1,13 @@ +#ifndef EXAMPLES_PIXMAN_TBM_HELPER_H +#define EXAMPLES_PIXMAN_TBM_HELPER_H + +#include +#include +#include +#include + +pixman_image_t * +pixman_image_from_tbm_surface(tbm_surface_h surface, + enum ds_buffer_data_ptr_access_flag access_flag); + +#endif diff --git a/src/examples/tbm-server-helper.c b/src/examples/tbm-server-helper.c index bd3a34d..320ee4f 100644 --- a/src/examples/tbm-server-helper.c +++ b/src/examples/tbm-server-helper.c @@ -8,6 +8,8 @@ #include static const struct ds_buffer_resource_interface tbm_buffer_resource_iface; +static const struct ds_buffer_interface tbm_client_buffer_iface; + static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data); static struct tbm_client_buffer * @@ -42,6 +44,19 @@ tbm_server_init_display(struct tbm_server *tbm, struct wl_display *display) return true; } +struct tbm_client_buffer * +tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + assert(ds_buffer->iface == &tbm_client_buffer_iface); + return (struct tbm_client_buffer *)ds_buffer; +} + +tbm_surface_h +tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer) +{ + return buffer->surface; +} + static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data) { @@ -107,15 +122,6 @@ static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { .from_resource = tbm_buffer_resource_iface_from_resource, }; -static const struct ds_buffer_interface tbm_client_buffer_iface; - -static struct tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) -{ - assert(ds_buffer->iface == &tbm_client_buffer_iface); - return (struct tbm_client_buffer *)ds_buffer; -} - static void tbm_client_buffer_destroy(struct ds_buffer *ds_buffer) { diff --git a/src/examples/tbm-server-helper.h b/src/examples/tbm-server-helper.h index a82ad5b..609f370 100644 --- a/src/examples/tbm-server-helper.h +++ b/src/examples/tbm-server-helper.h @@ -32,4 +32,10 @@ bool tbm_server_init_display(struct tbm_server *tbm_server, struct wl_display *display); +struct tbm_client_buffer * +tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); + +tbm_surface_h +tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer); + #endif diff --git a/src/examples/tinyds-tdm-renderer.c b/src/examples/tinyds-tdm-renderer.c new file mode 100644 index 0000000..0074dc9 --- /dev/null +++ b/src/examples/tinyds-tdm-renderer.c @@ -0,0 +1,187 @@ +#include +#include + +#include + +#include "pixman-helper.h" +#include "pixman-tbm-helper.h" +#include "tinyds-tdm-renderer.h" + +static void renderer_setup_thread(struct tinyds_renderer *renderer); +static void *renderer_thread_func(void *data); +static void texture_destroy(struct tinyds_texture *texture); + +bool +init_renderer(struct tinyds_renderer *renderer) +{ + renderer->damaged = false; + + wl_list_init(&renderer->textures); + + renderer_setup_thread(renderer); + + return true; +} + +void +fini_renderer(struct tinyds_renderer *renderer) +{ + pthread_mutex_lock(&renderer->mutex); + + renderer->destroying = true; + pthread_cond_signal(&renderer->cond); + + pthread_mutex_unlock(&renderer->mutex); + + pthread_join(renderer->worker_thread, NULL); + + pthread_mutex_destroy(&renderer->mutex); + pthread_cond_destroy(&renderer->cond); +} + +void +renderer_set_surface_queue(struct tinyds_renderer *renderer, + void *surface_queue) +{ + pthread_mutex_lock(&renderer->mutex); + + renderer->surface_queue = (tbm_surface_queue_h)surface_queue; + + pthread_mutex_unlock(&renderer->mutex); +} + +void +renderer_set_bg_color(struct tinyds_renderer *renderer, + uint8_t r, uint8_t g, uint8_t b) +{ + pixman_color_t color; + + pthread_mutex_lock(&renderer->mutex); + + color_rgb888(&color, r, g, b); + + renderer->bg_image = pixman_image_create_solid_fill(&color); + assert(renderer->bg_image); + + renderer->damaged = true; + + pthread_mutex_unlock(&renderer->mutex); +} + +void +renderer_add_texture(struct tinyds_renderer *renderer, + tbm_surface_h tbm_surface, int x, int y) +{ + struct tinyds_texture *texture; + + pthread_mutex_lock(&renderer->mutex); + + texture = calloc(1, sizeof *texture); + + texture->x = x; + texture->y = y; + texture->renderer = renderer; + texture->surface = tbm_surface; + texture->image = pixman_image_from_tbm_surface(tbm_surface, + DS_BUFFER_DATA_PTR_ACCESS_READ); + + wl_list_insert(renderer->textures.prev, &texture->link); + + ds_dbg("Add texture(%p)", texture); + + pthread_mutex_unlock(&renderer->mutex); +} + +void +renderer_draw(struct tinyds_renderer *renderer) +{ + pthread_mutex_lock(&renderer->mutex); + + renderer->damaged = true; + pthread_cond_signal(&renderer->cond); + + pthread_mutex_unlock(&renderer->mutex); +} + +static void +renderer_setup_thread(struct tinyds_renderer *renderer) +{ + pthread_mutex_init(&renderer->mutex, NULL); + pthread_cond_init(&renderer->cond, NULL); + pthread_create(&renderer->worker_thread, NULL, + renderer_thread_func, renderer); +} + +static void * +renderer_thread_func(void *data) +{ + struct tinyds_renderer *renderer = data; + struct tinyds_texture *texture, *texture_tmp; + pixman_image_t *dst_image; + tbm_surface_h surface; + tbm_surface_queue_error_e err; + + pthread_mutex_lock(&renderer->mutex); + + while (!renderer->destroying) { + if (!renderer->damaged) + pthread_cond_wait(&renderer->cond, &renderer->mutex); + + if (!renderer->damaged) + continue; + + if (!tbm_surface_queue_can_dequeue(renderer->surface_queue, 0)) + continue; + + ds_dbg(">> BEGIN DRAW"); + + err = tbm_surface_queue_dequeue(renderer->surface_queue, &surface); + assert(err == TBM_SURFACE_QUEUE_ERROR_NONE); + + dst_image = pixman_image_from_tbm_surface(surface, + DS_BUFFER_DATA_PTR_ACCESS_WRITE); + + if (renderer->bg_image) { + pixman_image_composite32(PIXMAN_OP_SRC, + renderer->bg_image, + NULL, + dst_image, + 0, 0, 0, 0, 0, 0, + pixman_image_get_width(dst_image), + pixman_image_get_height(dst_image)); + } + + wl_list_for_each_safe(texture, texture_tmp, &renderer->textures, link) { + ds_dbg("Draw texture(%p)", texture); + pixman_image_composite32(PIXMAN_OP_OVER, + texture->image, + NULL, + dst_image, + 0, 0, 0, 0, + texture->x, texture->y, + pixman_image_get_width(texture->image), + pixman_image_get_height(texture->image)); + texture_destroy(texture); + } + pixman_image_unref(dst_image); + + err = tbm_surface_queue_enqueue(renderer->surface_queue, surface); + assert(err == TBM_SURFACE_QUEUE_ERROR_NONE); + + renderer->damaged = false; + + ds_dbg("<< END DRAW"); + } + + pthread_mutex_unlock(&renderer->mutex); + + return NULL; +} + +static void +texture_destroy(struct tinyds_texture *texture) +{ + pixman_image_unref(texture->image); + wl_list_remove(&texture->link); + free(texture); +} diff --git a/src/examples/tinyds-tdm-renderer.h b/src/examples/tinyds-tdm-renderer.h new file mode 100644 index 0000000..5f3e6fd --- /dev/null +++ b/src/examples/tinyds-tdm-renderer.h @@ -0,0 +1,48 @@ +#ifndef EXAMPLES_TINYDS_TDM_RENDERER_H +#define EXAMPLES_TINYDS_TDM_RENDERER_H + +#include +#include +#include +#include +#include + +struct tinyds_renderer +{ + tbm_surface_queue_h surface_queue; + + struct wl_list textures; + + pthread_t worker_thread; + pthread_mutex_t mutex; + pthread_cond_t cond; + + pixman_image_t *bg_image; + + bool damaged; + bool destroying; +}; + +struct tinyds_texture +{ + struct tinyds_renderer *renderer; + pixman_image_t *image; + tbm_surface_h surface; + + struct wl_list link; + struct wl_listener buffer_destroy; + + int x, y; +}; + +bool init_renderer(struct tinyds_renderer *renderer); +void fini_renderer(struct tinyds_renderer *renderer); +void renderer_set_surface_queue(struct tinyds_renderer *renderer, + void *surface_queue); +void renderer_set_bg_color(struct tinyds_renderer *renderer, + uint8_t r, uint8_t g, uint8_t b); +void renderer_add_texture(struct tinyds_renderer *renderer, + tbm_surface_h tbm_surface, int x, int y); +void renderer_draw(struct tinyds_renderer *renderer); + +#endif diff --git a/src/examples/tinyds-tdm.c b/src/examples/tinyds-tdm.c index 143d53e..6ec1156 100644 --- a/src/examples/tinyds-tdm.c +++ b/src/examples/tinyds-tdm.c @@ -1,6 +1,3 @@ -#include "tbm-server-helper.h" -#include "pixman-helper.h" - #include #include #include @@ -14,12 +11,23 @@ #include #include #include -#include #include #include #include #include +#define USE_TDM_BUFFER_QUEUE + +#ifdef USE_TDM_BUFFER_QUEUE +#include "pixman-tbm-helper.h" +#include "tinyds-tdm-renderer.h" +#else +#include +#endif + +#include "tbm-server-helper.h" +#include "pixman-helper.h" + #define TINYDS_UNUSED __attribute__((unused)) struct tinyds_output @@ -27,7 +35,13 @@ struct tinyds_output struct tinyds_server *server; struct ds_output *ds_output; struct ds_allocator *allocator; +#ifdef USE_TDM_BUFFER_QUEUE + struct tinyds_renderer renderer; + struct ds_tdm_buffer_queue *buffer_queue; + struct wl_listener buffer_queue_acquirable; +#else struct ds_swapchain *swapchain; +#endif struct ds_buffer *front_buffer; struct wl_listener output_destroy; @@ -62,6 +76,7 @@ struct tinyds_view { struct tinyds_server *server; + struct tinyds_texture *texture; struct ds_xdg_surface *xdg_surface; struct wl_listener xdg_surface_map; @@ -82,7 +97,18 @@ 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_server_with_damage(struct tinyds_server *server); static void draw_output(struct tinyds_output *output); +static void output_swap_buffer(struct tinyds_output *output, + struct ds_buffer *buffer); +static void view_send_frame_done(struct tinyds_view *view); +#ifdef USE_TDM_BUFFER_QUEUE +static void output_buffer_queue_init(struct tinyds_output *output); +static void output_renderer_init(struct tinyds_output *output); +static void output_draw_with_renderer(struct tinyds_output *output); +#else +static void output_swapchain_init(struct tinyds_output *output); +static void output_draw_with_swapchain(struct tinyds_output *output); static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image); +#endif int main(void) @@ -150,10 +176,10 @@ view_handle_xdg_surface_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) { struct tinyds_view *view; + struct tinyds_server *server; view = wl_container_of(listener, view, xdg_surface_destroy); - - draw_server_with_damage(view->server); + server = view->server; wl_list_remove(&view->xdg_surface_destroy.link); wl_list_remove(&view->xdg_surface_map.link); @@ -161,6 +187,8 @@ view_handle_xdg_surface_destroy(struct wl_listener *listener, wl_list_remove(&view->surface_commit.link); wl_list_remove(&view->link); free(view); + + draw_server_with_damage(server); } static void @@ -237,32 +265,25 @@ backend_handle_new_output(struct wl_listener *listener, void *data) if (!output) return; - output->allocator = ds_tbm_allocator_create(); - if (!output->allocator) { - free(output); - return; - } - - output->swapchain = ds_swapchain_create(output->allocator, - mode->width, mode->height, DRM_FORMAT_XRGB8888); - if (!output->swapchain) { - ds_allocator_destroy(output->allocator); - free(output); - return; - } - output->server = server; output->ds_output = ds_output; + output->width = mode->width; + output->height = mode->height; output->drawable = true; output->damaged = true; +#ifdef USE_TDM_BUFFER_QUEUE + output_buffer_queue_init(output); + output_renderer_init(output); +#else + output_swapchain_init(output); +#endif + output->output_destroy.notify = output_handle_destroy; - ds_output_add_destroy_listener(ds_output, - &output->output_destroy); + ds_output_add_destroy_listener(ds_output, &output->output_destroy); output->output_frame.notify = output_handle_frame; - ds_output_add_frame_listener(ds_output, - &output->output_frame); + ds_output_add_frame_listener(ds_output, &output->output_frame); server->output = output; @@ -318,11 +339,15 @@ output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) if (output->front_buffer) ds_buffer_unlock(output->front_buffer); +#ifdef USE_TDM_BUFFER_QUEUE + fini_renderer(&output->renderer); +#else if (output->swapchain) ds_swapchain_destroy(output->swapchain); if (output->allocator) ds_allocator_destroy(output->allocator); +#endif wl_display_terminate(output->server->display); @@ -348,15 +373,102 @@ draw_server_with_damage(struct tinyds_server *server) draw_output(server->output); } +#ifdef USE_TDM_BUFFER_QUEUE static void -draw_output(struct tinyds_output *output) +output_handle_buffer_queue_acquirable(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_output *output; + struct ds_buffer *buffer; + + output = wl_container_of(listener, output, buffer_queue_acquirable); + + buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue); + assert(buffer); + + output_swap_buffer(output, buffer); +} + +static void +output_buffer_queue_init(struct tinyds_output *output) +{ + struct ds_tdm_output *tdm_output; + + tdm_output = ds_tdm_output_from_output(output->ds_output); + assert(tdm_output); + + output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output); + assert(output->buffer_queue); + + output->buffer_queue_acquirable.notify = + output_handle_buffer_queue_acquirable; + ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue, + &output->buffer_queue_acquirable); +} + +static void +output_renderer_init(struct tinyds_output *output) +{ + init_renderer(&output->renderer); + + renderer_set_surface_queue(&output->renderer, + ds_tdm_buffer_queue_get_native_queue(output->buffer_queue)); + + renderer_set_bg_color(&output->renderer, 80, 80, 80); +} + +static void +output_draw_with_renderer(struct tinyds_output *output) { - struct ds_buffer *output_buffer; - pixman_image_t *output_image; struct tinyds_view *view; - if (!output->drawable || !output->damaged) - return; + ds_dbg(">> BEGIN UPDATE TEXTURES"); + + wl_list_for_each(view, &output->server->views, link) { + struct ds_buffer *ds_buffer; + struct tbm_client_buffer *buffer; + tbm_surface_h surface; + + if (!view->mapped) + continue; + + ds_buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + assert(buffer); + + buffer = tbm_client_buffer_from_buffer(ds_buffer); + assert(buffer); + + surface = tbm_client_buffer_get_tbm_surface(buffer); + + renderer_add_texture(&output->renderer, surface, view->x, view->y); + + view_send_frame_done(view); + } + + ds_dbg("<< END UPDATE TEXTURES"); + + renderer_draw(&output->renderer); + +} +#else +static void +output_swapchain_init(struct tinyds_output *output) +{ + output->allocator = ds_tbm_allocator_create(); + assert(output->allocator); + + output->swapchain = ds_swapchain_create(output->allocator, + mode->width, mode->height, DRM_FORMAT_XRGB8888); + assert(output->swapchain); +} + +static void +output_draw_with_swapchain(struct tinyds_output *output) +{ + struct tinyds_view *view; + struct ds_buffer *output_buffer; + pixman_image_t *output_image; output_buffer = ds_swapchain_acquire(output->swapchain, NULL); if (!output_buffer) @@ -378,24 +490,7 @@ draw_output(struct tinyds_output *output) } pixman_image_unref(output_image); - ds_output_attach_buffer(output->ds_output, output_buffer); - ds_output_commit(output->ds_output); - - if (output->front_buffer) - ds_buffer_unlock(output->front_buffer); - output->front_buffer = output_buffer; - - output->drawable = false; - output->damaged = false; -} - -static void -view_send_frame_done(struct tinyds_view *view) -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface), - &now); + output_swap_buffer(output, output_buffer); } static void @@ -423,6 +518,44 @@ draw_view(struct tinyds_view *view, pixman_image_t *dst_image) view_send_frame_done(view); } +#endif + +static void +draw_output(struct tinyds_output *output) +{ + + if (!output->drawable || !output->damaged) + return; + +#ifdef USE_TDM_BUFFER_QUEUE + output_draw_with_renderer(output); +#else + output_draw_with_swapchain(output); +#endif + + output->drawable = false; + output->damaged = false; +} + +static void +output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer) +{ + ds_output_attach_buffer(output->ds_output, buffer); + ds_output_commit(output->ds_output); + + if (output->front_buffer) + ds_buffer_unlock(output->front_buffer); + output->front_buffer = buffer; +} + +static void +view_send_frame_done(struct tinyds_view *view) +{ + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface), + &now); +} static int server_dispatch_stdin(int fd, uint32_t mask, void *data) -- 2.7.4 From acd4b133b69e5a18f2effbe684545eee40efd5f3 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 17 Mar 2022 19:52:29 +0900 Subject: [PATCH 10/16] Fix typo on a word of header guard Change-Id: I780a95bc06fda2a2e71630741e949da011457069 --- src/libds-tizen/backend/tdm/tdm_buffer_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libds-tizen/backend/tdm/tdm_buffer_queue.h b/src/libds-tizen/backend/tdm/tdm_buffer_queue.h index 774b7c3..a983265 100644 --- a/src/libds-tizen/backend/tdm/tdm_buffer_queue.h +++ b/src/libds-tizen/backend/tdm/tdm_buffer_queue.h @@ -1,5 +1,5 @@ #ifndef DS_TIZEN_BACKEND_TDM_BUFFER_QUEUE_H -#define DS_TIZEN_BACKEND_TBM_BUFFER_QUEUE_H +#define DS_TIZEN_BACKEND_TDM_BUFFER_QUEUE_H #include #include -- 2.7.4 From d59ec989f24b316865d7b78f301926b091362b32 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Mon, 28 Mar 2022 20:03:20 +0900 Subject: [PATCH 11/16] Add ds_tbm_server ds_tbm_server initializes wayland_tbm to allow wl_client to use tbm_surface as a wl_buffer. Change-Id: I5fcf1f37bd9f410f7d400ac3a918c159dbb07fbc --- include/libds-tizen/tbm_server.h | 24 +++ src/examples/meson.build | 6 +- src/examples/tbm-server-helper.h | 41 ----- src/examples/tinyds-tdm.c | 23 ++- src/libds-tizen/meson.build | 8 +- src/libds-tizen/pixel_format.c | 61 ++++++ src/libds-tizen/pixel_format.h | 10 + .../tbm_server.c} | 204 ++++++++++++--------- src/libds-tizen/tbm_server.h | 34 ++++ 9 files changed, 272 insertions(+), 139 deletions(-) create mode 100644 include/libds-tizen/tbm_server.h delete mode 100644 src/examples/tbm-server-helper.h create mode 100644 src/libds-tizen/pixel_format.c create mode 100644 src/libds-tizen/pixel_format.h rename src/{examples/tbm-server-helper.c => libds-tizen/tbm_server.c} (66%) create mode 100644 src/libds-tizen/tbm_server.h diff --git a/include/libds-tizen/tbm_server.h b/include/libds-tizen/tbm_server.h new file mode 100644 index 0000000..c48977e --- /dev/null +++ b/include/libds-tizen/tbm_server.h @@ -0,0 +1,24 @@ +#ifndef LIBDS_TIZEN_TBM_SERVER_H +#define LIBDS_TIZEN_TBM_SERVER_H + +#include +#include + +struct ds_tbm_server; + +struct ds_tbm_client_buffer; + +struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display); + +void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener); + +struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); + +tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer); + +#endif diff --git a/src/examples/meson.build b/src/examples/meson.build index c60b610..ddb0792 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -35,19 +35,15 @@ if get_option('tizen') tinyds_tdm_files = [ 'tinyds-tdm.c', - 'tinyds-tdm-renderer.c', - 'tbm-server-helper.c', 'pixman-helper.c', 'pixman-tbm-helper.c', + 'tinyds-tdm-renderer.c', ] executable('tinyds-tdm', tinyds_tdm_files, dependencies: [ common_deps, dependency('pixman-1', required: true), - dependency('libdrm', required: true), - dependency('libtbm', required: true), - dependency('wayland-tbm-server', required: true), dependency('threads', required: true), ], install_dir: libds_bindir, diff --git a/src/examples/tbm-server-helper.h b/src/examples/tbm-server-helper.h deleted file mode 100644 index 609f370..0000000 --- a/src/examples/tbm-server-helper.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef EXAMPLES_TBM_SERVER_H -#define EXAMPLES_TBM_SERVER_H - -#include -#include -#include -#include -#include - -struct tbm_server -{ - struct wayland_tbm_server *wl_tbm; - - struct wl_listener display_destroy; -}; - -struct tbm_client_buffer -{ - struct ds_buffer base; - - tbm_surface_h surface; - struct wl_resource *resource; - - struct wl_listener buffer_release; - struct wl_listener resource_destroy; - - uint32_t format; - size_t stride; -}; - -bool -tbm_server_init_display(struct tbm_server *tbm_server, - struct wl_display *display); - -struct tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); - -tbm_surface_h -tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer); - -#endif diff --git a/src/examples/tinyds-tdm.c b/src/examples/tinyds-tdm.c index 6ec1156..c14cb9e 100644 --- a/src/examples/tinyds-tdm.c +++ b/src/examples/tinyds-tdm.c @@ -15,6 +15,7 @@ #include #include #include +#include #define USE_TDM_BUFFER_QUEUE @@ -25,7 +26,6 @@ #include #endif -#include "tbm-server-helper.h" #include "pixman-helper.h" #define TINYDS_UNUSED __attribute__((unused)) @@ -55,7 +55,7 @@ struct tinyds_output struct tinyds_server { - struct tbm_server tbm_server; + struct ds_tbm_server *tbm_server; struct wl_display *display; @@ -127,9 +127,6 @@ main(void) res = init_server(server, display); assert(res); - res = tbm_server_init_display(&server->tbm_server, display); - assert(res); - socket = wl_display_add_socket_auto(display); assert(socket); @@ -314,6 +311,12 @@ init_server(struct tinyds_server *server, struct wl_display *display) return false; } + server->tbm_server = ds_tbm_server_create(display); + if (!server->tbm_server) { + ds_backend_destroy(server->backend); + return false; + } + server->xdg_shell = ds_xdg_shell_create(display); if (!server->xdg_shell) { ds_backend_destroy(server->backend); @@ -426,7 +429,7 @@ output_draw_with_renderer(struct tinyds_output *output) wl_list_for_each(view, &output->server->views, link) { struct ds_buffer *ds_buffer; - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *tbm_buffer; tbm_surface_h surface; if (!view->mapped) @@ -434,12 +437,12 @@ output_draw_with_renderer(struct tinyds_output *output) ds_buffer = ds_surface_get_buffer( ds_xdg_surface_get_surface(view->xdg_surface)); - assert(buffer); + assert(ds_buffer); - buffer = tbm_client_buffer_from_buffer(ds_buffer); - assert(buffer); + tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); + assert(tbm_buffer); - surface = tbm_client_buffer_get_tbm_surface(buffer); + surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer); renderer_add_texture(&output->renderer, surface, view->x, view->y); diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build index e9ca734..4f76b68 100644 --- a/src/libds-tizen/meson.build +++ b/src/libds-tizen/meson.build @@ -1,7 +1,13 @@ -libds_tizen_files = [] +libds_tizen_files = [ + 'pixel_format.c', + 'tbm_server.c', +] libds_tizen_deps = [ dep_libds, + dependency('libdrm', required: true), + dependency('libtbm', required: true), + dependency('wayland-tbm-server', required: true), ] subdir('allocator') diff --git a/src/libds-tizen/pixel_format.c b/src/libds-tizen/pixel_format.c new file mode 100644 index 0000000..021652e --- /dev/null +++ b/src/libds-tizen/pixel_format.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include "libds/log.h" +#include "pixel_format.h" + +#ifdef ARRAY_LENGTH +#undef ARRAY_LENGTH +#endif + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +struct ds_tbm_format +{ + uint32_t drm_format; + uint32_t tbm_format; +}; + +static const struct ds_tbm_format formats[] = +{ + { + .drm_format = DRM_FORMAT_ARGB8888, + .tbm_format = TBM_FORMAT_ARGB8888, + }, + { + .drm_format = DRM_FORMAT_XRGB8888, + .tbm_format = TBM_FORMAT_XRGB8888, + }, + /* TODO more format */ +}; + +uint32_t +convert_drm_format_to_tbm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].drm_format == fmt) + return formats[i].tbm_format; + } + + ds_err("DRM format 0x%"PRIX32" has no TBM equivalent", fmt); + + return 0; +} + +uint32_t +convert_tbm_format_to_drm(uint32_t fmt) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(formats); i++) { + if (formats[i].tbm_format == fmt) + return formats[i].drm_format; + } + + ds_err("TBM format 0x%"PRIX32" has no DRM equivalent", fmt); + + return 0; +} diff --git a/src/libds-tizen/pixel_format.h b/src/libds-tizen/pixel_format.h new file mode 100644 index 0000000..a63d096 --- /dev/null +++ b/src/libds-tizen/pixel_format.h @@ -0,0 +1,10 @@ +#ifndef DS_TIZEN_PIXEL_FORMAT_H +#define DS_TIZEN_PIXEL_FORMAT_H + +#include + +uint32_t convert_drm_format_to_tbm(uint32_t fmt); + +uint32_t convert_tbm_format_to_drm(uint32_t fmt); + +#endif diff --git a/src/examples/tbm-server-helper.c b/src/libds-tizen/tbm_server.c similarity index 66% rename from src/examples/tbm-server-helper.c rename to src/libds-tizen/tbm_server.c index 320ee4f..ecb46db 100644 --- a/src/examples/tbm-server-helper.c +++ b/src/libds-tizen/tbm_server.c @@ -1,82 +1,111 @@ -#include "tbm-server-helper.h" - #include #include #include -#include + #include -#include + +#include "libds/log.h" +#include "pixel_format.h" +#include "tbm_server.h" static const struct ds_buffer_resource_interface tbm_buffer_resource_iface; static const struct ds_buffer_interface tbm_client_buffer_iface; static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data); -static struct tbm_client_buffer * -tbm_client_buffer_create(struct wl_resource *resource); -bool -tbm_server_init_display(struct tbm_server *tbm, struct wl_display *display) +WL_EXPORT struct ds_tbm_server * +ds_tbm_server_create(struct wl_display *display) { + struct ds_tbm_server *tbm; tbm_bufmgr bufmgr; + tbm = calloc(1, sizeof *tbm); + if (!tbm) + return NULL; + + wl_signal_init(&tbm->events.destroy); + tbm->wl_tbm = wayland_tbm_server_init(display, NULL, -1, 0); if (!tbm->wl_tbm) { - return false; + goto err_wl_tbm; } bufmgr = wayland_tbm_server_get_bufmgr(tbm->wl_tbm); if (!bufmgr) { - wayland_tbm_server_deinit(tbm->wl_tbm); - return false; + goto err_bind; } if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display)) { - wayland_tbm_server_deinit(tbm->wl_tbm); - return false; + goto err_bind; } - ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); - tbm->display_destroy.notify = tbm_server_handle_display_destroy; wl_display_add_destroy_listener(display, &tbm->display_destroy); - return true; + ds_buffer_register_resource_interface(&tbm_buffer_resource_iface); + + return tbm; + +err_bind: + wayland_tbm_server_deinit(tbm->wl_tbm); +err_wl_tbm: + free(tbm); + + return NULL; } -struct tbm_client_buffer * -tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +WL_EXPORT void +ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm, + struct wl_listener *listener) { - assert(ds_buffer->iface == &tbm_client_buffer_iface); - return (struct tbm_client_buffer *)ds_buffer; + wl_signal_add(&tbm->events.destroy, listener); +} + +WL_EXPORT struct ds_tbm_client_buffer * +ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) +{ + if (ds_buffer->iface != &tbm_client_buffer_iface) + return NULL; + return (struct ds_tbm_client_buffer *)ds_buffer; } -tbm_surface_h -tbm_client_buffer_get_tbm_surface(struct tbm_client_buffer *buffer) +WL_EXPORT tbm_surface_h +ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer) { + if (buffer->base.iface != &tbm_client_buffer_iface) + return NULL; return buffer->surface; } static void tbm_server_handle_display_destroy(struct wl_listener *listener, void *data) { - struct tbm_server *tbm; + struct ds_tbm_server *tbm; tbm = wl_container_of(listener, tbm, display_destroy); + + wl_signal_emit(&tbm->events.destroy, tbm); + wayland_tbm_server_deinit(tbm->wl_tbm); + free(tbm); } -static bool -tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +static void +tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) { - return !!wayland_tbm_server_get_surface(NULL, resource); + struct ds_tbm_client_buffer *buffer; + + buffer = wl_container_of(listener, buffer, buffer_release); + if (buffer->resource) + wl_buffer_send_release(buffer->resource); } static void tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, void *data) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = wl_container_of(listener, buffer, resource_destroy); @@ -88,44 +117,17 @@ tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener, ds_buffer_drop(&buffer->base); } -static struct tbm_client_buffer * -tbm_client_buffer_get_or_create(struct wl_resource *resource) -{ - struct tbm_client_buffer *buffer; - struct wl_listener *resource_destroy_listener; - - resource_destroy_listener = wl_resource_get_destroy_listener(resource, - tbm_client_buffer_handle_resource_destroy);; - if (resource_destroy_listener) { - buffer = wl_container_of(resource_destroy_listener, - buffer, resource_destroy); - return buffer; - } - - return tbm_client_buffer_create(resource); -} - -static struct ds_buffer * -tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +static struct ds_tbm_client_buffer * +tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; - - buffer = tbm_client_buffer_get_or_create(resource); - assert(buffer); - - return &buffer->base; + assert(ds_buffer->iface == &tbm_client_buffer_iface); + return (struct ds_tbm_client_buffer *)ds_buffer; } -static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { - .name = "tbm", - .is_instance = tbm_buffer_resource_iface_is_instance, - .from_resource = tbm_buffer_resource_iface_from_resource, -}; - static void -tbm_client_buffer_destroy(struct ds_buffer *ds_buffer) +tbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = tbm_client_buffer_from_buffer(ds_buffer); @@ -137,11 +139,11 @@ tbm_client_buffer_destroy(struct ds_buffer *ds_buffer) } static bool -tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, +tbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer, enum ds_buffer_data_ptr_access_flag flags, void **data, uint32_t *format, size_t *stride) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; tbm_surface_info_s info; tbm_bo_access_option op = TBM_OPTION_NONE; int err; @@ -160,7 +162,7 @@ tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, return false; } - *format = DRM_FORMAT_XRGB8888; // FIXME + *format = convert_tbm_format_to_drm(buffer->format); *stride = info.planes[0].stride; *data = info.planes[0].ptr; @@ -168,9 +170,9 @@ tbm_client_buffer_begin_data_ptr_access(struct ds_buffer *ds_buffer, } static void -tbm_client_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer) +tbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; buffer = tbm_client_buffer_from_buffer(ds_buffer); @@ -178,36 +180,31 @@ tbm_client_buffer_end_data_ptr_access(struct ds_buffer *ds_buffer) } static const struct ds_buffer_interface tbm_client_buffer_iface = { - .destroy = tbm_client_buffer_destroy, - .begin_data_ptr_access = tbm_client_buffer_begin_data_ptr_access, - .end_data_ptr_access = tbm_client_buffer_end_data_ptr_access, + .destroy = tbm_client_buffer_iface_destroy, + .begin_data_ptr_access = tbm_client_buffer_iface_begin_data_ptr_access, + .end_data_ptr_access = tbm_client_buffer_iface_end_ptr_access, }; -static void -tbm_client_buffer_handle_release(struct wl_listener *listener, void *data) -{ - struct tbm_client_buffer *buffer; - - buffer = wl_container_of(listener, buffer, buffer_release); - if (buffer->resource) - wl_buffer_send_release(buffer->resource); -} - -static struct tbm_client_buffer * +static struct ds_tbm_client_buffer * tbm_client_buffer_create(struct wl_resource *resource) { - struct tbm_client_buffer *buffer; + struct ds_tbm_client_buffer *buffer; tbm_surface_h surface; int32_t width, height; surface = wayland_tbm_server_get_surface(NULL, resource); - assert(surface); + if (!surface) { + ds_err("Could not get tbm_surface from wl_resource@%d", + wl_resource_get_id(resource)); + return NULL; + } width = tbm_surface_get_width(surface); height = tbm_surface_get_height(surface); buffer = calloc(1, sizeof *buffer); - assert(buffer); + if (!buffer) + return NULL; ds_buffer_init(&buffer->base, &tbm_client_buffer_iface, width, height); @@ -226,3 +223,46 @@ tbm_client_buffer_create(struct wl_resource *resource) return buffer; } + +static struct ds_tbm_client_buffer * +tbm_client_buffer_get_or_create(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + struct wl_listener *resource_destroy_listener; + + resource_destroy_listener = wl_resource_get_destroy_listener(resource, + tbm_client_buffer_handle_resource_destroy);; + if (resource_destroy_listener) { + buffer = wl_container_of(resource_destroy_listener, + buffer, resource_destroy); + return buffer; + } + + return tbm_client_buffer_create(resource); +} + +static bool +tbm_buffer_resource_iface_is_instance(struct wl_resource *resource) +{ + return !!wayland_tbm_server_get_surface(NULL, resource); +} + +static struct ds_buffer * +tbm_buffer_resource_iface_from_resource(struct wl_resource *resource) +{ + struct ds_tbm_client_buffer *buffer; + + buffer = tbm_client_buffer_get_or_create(resource); + if (!buffer) { + ds_err("Could not get or create ds_tbm_client_buffer"); + return NULL; + } + + return &buffer->base; +} + +static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = { + .name = "tbm", + .is_instance = tbm_buffer_resource_iface_is_instance, + .from_resource = tbm_buffer_resource_iface_from_resource, +}; diff --git a/src/libds-tizen/tbm_server.h b/src/libds-tizen/tbm_server.h new file mode 100644 index 0000000..be56746 --- /dev/null +++ b/src/libds-tizen/tbm_server.h @@ -0,0 +1,34 @@ +#ifndef DS_TIZEN_TBM_SERVER_H +#define DS_TIZEN_TBM_SERVER_H + +#include +#include +#include +#include "libds/interfaces/buffer.h" + +struct ds_tbm_server +{ + struct wayland_tbm_server *wl_tbm; + + struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + } events; +}; + +struct ds_tbm_client_buffer +{ + struct ds_buffer base; + + tbm_surface_h surface; + struct wl_resource *resource; + + struct wl_listener buffer_release; + struct wl_listener resource_destroy; + + uint32_t format; + size_t stride; +}; + +#endif -- 2.7.4 From 4d7b56860860629047323bd3bb451f36f7e211c4 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 30 Mar 2022 16:44:45 +0900 Subject: [PATCH 12/16] add extern 'C' at tbm_server.h Change-Id: I18ffdda44282b470ea96edef8cd572cbe7688bce --- include/libds-tizen/tbm_server.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/libds-tizen/tbm_server.h b/include/libds-tizen/tbm_server.h index c48977e..f1cc97d 100644 --- a/include/libds-tizen/tbm_server.h +++ b/include/libds-tizen/tbm_server.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + struct ds_tbm_server; struct ds_tbm_client_buffer; @@ -21,4 +25,8 @@ ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer); tbm_surface_h ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer); +#ifdef __cplusplus +} +#endif + #endif -- 2.7.4 From a4cf679d920de75938da6d61de99940cd36c24ef Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 30 Mar 2022 19:57:41 +0900 Subject: [PATCH 13/16] add ws_members as reviewers Change-Id: If915ead2bd39e85ed26a75fc83e7514024aca4bd --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 2c7fc6d..b37075e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,5 +5,5 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @doyoun-kang @gl77-lee @sc1-lim @shiin-lee +* @TizenWS/ws_members -- 2.7.4 From 0f13f2dc853acf179cc59b0fe1f5269e45beadf5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9E=84=EC=88=98=EC=B0=AC/Tizen=20Platform=20Lab=28SR=29/?= =?utf8?q?=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Mon, 11 Apr 2022 09:27:40 +0900 Subject: [PATCH 14/16] Update CODEOWNERS Change-Id: I5a2b3c8ba058912115ad56e0366dc54341d19e9b --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index b37075e..a215b9e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,5 +5,5 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @TizenWS/ws_members +* @TizenWS/ws_members @sc1-lim @shiin-lee @joonbum-ko @cyeon-lee @doyoun-kang @gl77-lee @duna-oh @jinbong-lee @jk0430-kim @juns-kim @TizenWS/ws_members -- 2.7.4 From 7b8ec61e92e068521fdc968c998b8e2b6693e85a Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9E=84=EC=88=98=EC=B0=AC/Tizen=20Platform=20Lab=28SR=29/?= =?utf8?q?=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Mon, 11 Apr 2022 09:27:52 +0900 Subject: [PATCH 15/16] Update CODEOWNERS Change-Id: I8806c08d307bf3e117c623991b0960b7046477a4 --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index a215b9e..d52bfc2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,5 +5,5 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @TizenWS/ws_members @sc1-lim @shiin-lee @joonbum-ko @cyeon-lee @doyoun-kang @gl77-lee @duna-oh @jinbong-lee @jk0430-kim @juns-kim @TizenWS/ws_members +* @sc1-lim @shiin-lee @joonbum-ko @cyeon-lee @doyoun-kang @gl77-lee @duna-oh @jinbong-lee @jk0430-kim @juns-kim @TizenWS/ws_members -- 2.7.4 From f4624065b9715e474d2aaaf82b5613a0165ff148 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 7 Apr 2022 10:46:48 +0900 Subject: [PATCH 16/16] Add ds_input_device, and ds_pointer. This patch is just the beginning of ds_input_device. Currently, a ds_input_device is created only on the wayland backend, and it only supports a ds_pointer. Other devices like keyboard and touch, and other backends like libinput will be supported in future patches. Change-Id: I9efce1bea5fd362d5bcee86d92a81076b0be48bc --- include/libds/backend.h | 4 + include/libds/input_device.h | 31 +++ include/libds/interfaces/backend.h | 1 + include/libds/interfaces/input_device.h | 40 ++++ include/libds/interfaces/pointer.h | 30 +++ include/libds/pointer.h | 38 +++ src/examples/meson.build | 9 + src/examples/pointer-test.c | 278 ++++++++++++++++++++++ src/libds/backend.c | 8 + src/libds/backend/wayland/backend.c | 27 ++- src/libds/backend/wayland/backend.h | 61 +++++ src/libds/backend/wayland/meson.build | 1 + src/libds/backend/wayland/output.c | 28 +++ src/libds/backend/wayland/seat.c | 406 ++++++++++++++++++++++++++++++++ src/libds/input_device.c | 69 ++++++ src/libds/meson.build | 2 + src/libds/pointer.c | 55 +++++ 17 files changed, 1083 insertions(+), 5 deletions(-) create mode 100644 include/libds/input_device.h create mode 100644 include/libds/interfaces/input_device.h create mode 100644 include/libds/interfaces/pointer.h create mode 100644 include/libds/pointer.h create mode 100644 src/examples/pointer-test.c create mode 100644 src/libds/backend/wayland/seat.c create mode 100644 src/libds/input_device.c create mode 100644 src/libds/pointer.c diff --git a/include/libds/backend.h b/include/libds/backend.h index 6b587d2..d6a266f 100644 --- a/include/libds/backend.h +++ b/include/libds/backend.h @@ -31,6 +31,10 @@ void ds_backend_add_new_output_listener(struct ds_backend *backend, struct wl_listener *listener); +void +ds_backend_add_new_input_listener(struct ds_backend *backend, + struct wl_listener *listener); + #ifdef __cplusplus } #endif diff --git a/include/libds/input_device.h b/include/libds/input_device.h new file mode 100644 index 0000000..45e125b --- /dev/null +++ b/include/libds/input_device.h @@ -0,0 +1,31 @@ +#ifndef LIBDS_INPUT_DEVICE_H +#define LIBDS_INPUT_DEVICE_H + +struct ds_input_device; + +struct ds_pointer; + +enum ds_button_state +{ + DS_BUTTON_RELEASED, + DS_BUTTON_PRESSED, +}; + +enum ds_input_device_type +{ + DS_INPUT_DEVICE_POINTER, + DS_INPUT_DEVICE_KEYBOARD, + DS_INPUT_DEVICE_TOUCH, +}; + +enum ds_input_device_type +ds_input_device_get_type(struct ds_input_device *dev); + +struct ds_pointer * +ds_input_device_get_pointer(struct ds_input_device *dev); + +void +ds_input_device_add_destroy_listener(struct ds_input_device *dev, + struct wl_listener *listener); + +#endif diff --git a/include/libds/interfaces/backend.h b/include/libds/interfaces/backend.h index e960ac4..bad37a0 100644 --- a/include/libds/interfaces/backend.h +++ b/include/libds/interfaces/backend.h @@ -22,6 +22,7 @@ struct ds_backend { struct wl_signal destroy; struct wl_signal new_output; + struct wl_signal new_input; } events; bool started; diff --git a/include/libds/interfaces/input_device.h b/include/libds/interfaces/input_device.h new file mode 100644 index 0000000..f31594b --- /dev/null +++ b/include/libds/interfaces/input_device.h @@ -0,0 +1,40 @@ +#ifndef LIBDS_INTERFACES_INPUT_DEVICE_H +#define LIBDS_INTERFACES_INPUT_DEVICE_H + +#include +#include +#include + +struct ds_input_device_interface +{ + void (*destroy)(struct ds_input_device *dev); +}; + +struct ds_input_device +{ + const struct ds_input_device_interface *iface; + + char *name; + double width_mm, height_mm; + char *output_name; + + enum ds_input_device_type type; + union { + void *_device; + struct ds_pointer *pointer; + }; + + struct { + struct wl_signal destroy; + } events; + + struct wl_list link; +}; + +void ds_input_device_init(struct ds_input_device *dev, + enum ds_input_device_type type, + const struct ds_input_device_interface *iface, + const char *name, int vendor, int product); +void ds_input_device_destroy(struct ds_input_device *dev); + +#endif diff --git a/include/libds/interfaces/pointer.h b/include/libds/interfaces/pointer.h new file mode 100644 index 0000000..84b0e23 --- /dev/null +++ b/include/libds/interfaces/pointer.h @@ -0,0 +1,30 @@ +#ifndef LIBDS_INTERFACES_POINTER_H +#define LIBDS_INTERFACES_POINTER_H + +#include + +struct ds_pointer; + +struct ds_pointer_interface +{ + void (*destroy)(struct ds_pointer *pointer); +}; + +struct ds_pointer +{ + const struct ds_pointer_interface *iface; + + struct { + struct wl_signal motion; + struct wl_signal motion_absolute; + struct wl_signal button; + struct wl_signal frame; + } events; +}; + +void ds_pointer_init(struct ds_pointer *pointer, + const struct ds_pointer_interface *iface); + +void ds_pointer_destroy(struct ds_pointer *pointer); + +#endif diff --git a/include/libds/pointer.h b/include/libds/pointer.h new file mode 100644 index 0000000..30bfaca --- /dev/null +++ b/include/libds/pointer.h @@ -0,0 +1,38 @@ +#ifndef LIBDS_POINTER_H +#define LIBDS_POINTER_H + +#include +#include +#include + +struct ds_pointer; + +struct ds_event_pointer_motion_absolute +{ + struct ds_input_device *device; + uint32_t time_msec; + // From 0..1 + double x, y; +}; + +struct ds_event_pointer_button +{ + struct ds_input_device *device; + uint32_t time_msec; + uint32_t button; + enum ds_button_state state; +}; + +void ds_pointer_add_motion_listener(struct ds_pointer *pointer, + struct wl_listener *listener); + +void ds_pointer_add_motion_absolute_listener(struct ds_pointer *pointer, + struct wl_listener *listener); + +void ds_pointer_add_button_listener(struct ds_pointer *pointer, + struct wl_listener *listener); + +void ds_pointer_add_frame_listener(struct ds_pointer *pointer, + struct wl_listener *listener); + +#endif diff --git a/src/examples/meson.build b/src/examples/meson.build index ddb0792..f19f139 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -23,6 +23,15 @@ executable('tinyds', install : true ) +executable('pointer-test', + [ + 'pointer-test.c', + 'pixman-helper.c', + ], + dependencies: common_deps, + install_dir: libds_bindir, + install : true) + if get_option('tizen') common_deps += dep_libds_tizen diff --git a/src/examples/pointer-test.c b/src/examples/pointer-test.c new file mode 100644 index 0000000..d669a03 --- /dev/null +++ b/src/examples/pointer-test.c @@ -0,0 +1,278 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pixman-helper.h" + +#define WIDTH 700 +#define HEIGHT 400 + +struct pointer_device { + struct ds_pointer *ds_pointer; + + struct wl_listener destroy; + struct wl_listener motion_absolute; + struct wl_listener button; + struct wl_listener frame; +}; + +struct output +{ + struct server *server; + + struct ds_output *ds_output; + struct ds_allocator *allocator; + struct ds_swapchain *swapchain; + + struct ds_buffer *front_buffer; + + struct wl_listener destroy; +}; + +struct server +{ + struct wl_display *display; + + struct output output; + + struct ds_backend *backend; + + struct wl_listener backend_destroy; + struct wl_listener new_input; +}; + +struct server _server; + +static struct ds_backend *create_backend_auto(struct wl_display *display); +static void handle_backend_destroy(struct wl_listener *listener, void *data); +static void handle_new_input(struct wl_listener *listener, void *data); +static void output_init(struct output *output, struct server *sever); +static void output_draw(struct output *output); + +int +main(void) +{ + struct server *server = &_server; + + ds_log_init(DS_DBG, NULL); + + server->display = wl_display_create(); + assert(server->display); + + server->backend = create_backend_auto(server->display); + assert(server->backend); + + server->backend_destroy.notify = handle_backend_destroy; + ds_backend_add_destroy_listener(server->backend, &server->backend_destroy); + + server->new_input.notify = handle_new_input; + ds_backend_add_new_input_listener(server->backend, &server->new_input); + + output_init(&server->output, server); + + ds_backend_start(server->backend); + + output_draw(&server->output); + + wl_display_run(server->display); + + wl_display_destroy(server->display); + + return 0; +} + +static struct ds_backend * +create_backend_auto(struct wl_display *display) +{ + struct ds_backend *backend = NULL; + char name[512]; + int i; + + for (i = 0; i < 5; i++) { + snprintf(name, sizeof name, "wayland-%d", i); + backend = ds_wl_backend_create(display, name); + if (backend) + break; + } + + return backend; +} + +static void +handle_backend_destroy(struct wl_listener *listener, void *data) +{ + struct server *server; + + server = wl_container_of(listener, server, backend_destroy); + + wl_list_remove(&server->backend_destroy.link); + wl_list_remove(&server->new_input.link); +} + +static char * +device_type_to_string(enum ds_input_device_type type) +{ + switch (type) { + case DS_INPUT_DEVICE_POINTER: + return "pointer"; + break; + case DS_INPUT_DEVICE_KEYBOARD: + return "keyboard"; + break; + case DS_INPUT_DEVICE_TOUCH: + return "touch"; + break; + default: + return "Unknown"; + } +} + +static void +pointer_handle_device_destroy(struct wl_listener *listener, void *data) +{ + struct pointer_device *pointer; + + pointer = wl_container_of(listener, pointer, destroy); + + wl_list_remove(&pointer->destroy.link); + wl_list_remove(&pointer->motion_absolute.link); + wl_list_remove(&pointer->button.link); + wl_list_remove(&pointer->frame.link); + + free(pointer); +} + +static void +pointer_handle_motion_absolute(struct wl_listener *listener, void *data) +{ + struct ds_event_pointer_motion_absolute *event = data; + + ds_inf("Pointer device(%p): motion absolute (%f, %f) time(%d ms)", + event->device, event->x, event->y, event->time_msec); +} + +static void +pointer_handle_button(struct wl_listener *listener, void *data) +{ + struct ds_event_pointer_button *event = data; + + ds_inf("Pointer Device(%p): button(%d) state(%d) time(%d ms)", + event->device, event->button, event->state, event->time_msec); +} + +static void +pointer_handle_frame(struct wl_listener *listener, void *data) +{ + ds_inf("Pointer device(%p): frame", data); +} + +static void +add_pointer(struct ds_input_device *dev) +{ + struct pointer_device *pointer; + + pointer = calloc(1, sizeof *pointer); + if (!pointer) + return; + + pointer->ds_pointer = ds_input_device_get_pointer(dev); + + pointer->destroy.notify = pointer_handle_device_destroy; + ds_input_device_add_destroy_listener(dev, &pointer->destroy); + + pointer->motion_absolute.notify = pointer_handle_motion_absolute; + ds_pointer_add_motion_absolute_listener(pointer->ds_pointer, + &pointer->motion_absolute); + + pointer->button.notify = pointer_handle_button; + ds_pointer_add_button_listener(pointer->ds_pointer, + &pointer->button); + + pointer->frame.notify = pointer_handle_frame; + ds_pointer_add_frame_listener(pointer->ds_pointer, + &pointer->frame); +} + +static void +handle_new_input(struct wl_listener *listener, void *data) +{ + struct ds_input_device *dev = data; + enum ds_input_device_type type; + + type = ds_input_device_get_type(dev); + + if (type != DS_INPUT_DEVICE_POINTER) + return; + + ds_inf("New pointer device(%p) type(%s)", dev, + device_type_to_string(type)); + + add_pointer(dev); +} + +static void +output_handle_destroy(struct wl_listener *listener, void *data) +{ + struct output *output; + + output = wl_container_of(listener, output, destroy); + + wl_list_remove(&output->destroy.link); + + ds_swapchain_destroy(output->swapchain); + ds_allocator_destroy(output->allocator); +} + +static void +output_init(struct output *output, struct server *server) +{ + output->server = server; + + output->ds_output = ds_wl_backend_create_output(server->backend); + assert(output->ds_output); + + output->destroy.notify = output_handle_destroy; + ds_output_add_destroy_listener(output->ds_output, &output->destroy); + + output->allocator = ds_shm_allocator_create(); + assert(output->allocator); + + output->swapchain = ds_swapchain_create(output->allocator, + WIDTH, HEIGHT, DRM_FORMAT_XRGB8888); + assert(output->swapchain); +} + +static void +output_draw(struct output *output) +{ + struct ds_buffer *buffer; + pixman_image_t *img; + + ds_dbg("Redraw output"); + + buffer = ds_swapchain_acquire(output->swapchain, NULL); + assert(buffer); + + img = pixman_image_from_buffer(buffer, DS_BUFFER_DATA_PTR_ACCESS_WRITE); + assert(img); + + pixman_image_fill_color(img, 80, 80, 80); + + pixman_image_unref(img); + + ds_output_attach_buffer(output->ds_output, buffer); + ds_output_commit(output->ds_output); + + if (output->front_buffer) + ds_buffer_unlock(output->front_buffer); + + output->front_buffer = buffer; +} diff --git a/src/libds/backend.c b/src/libds/backend.c index ee2a912..641374a 100644 --- a/src/libds/backend.c +++ b/src/libds/backend.c @@ -41,6 +41,13 @@ ds_backend_add_new_output_listener(struct ds_backend *backend, wl_signal_add(&backend->events.new_output, listener); } +WL_EXPORT void +ds_backend_add_new_input_listener(struct ds_backend *backend, + struct wl_listener *listener) +{ + wl_signal_add(&backend->events.new_input, listener); +} + void ds_backend_init(struct ds_backend *backend, const struct ds_backend_interface *iface) @@ -48,6 +55,7 @@ ds_backend_init(struct ds_backend *backend, backend->iface = iface; wl_signal_init(&backend->events.destroy); wl_signal_init(&backend->events.new_output); + wl_signal_init(&backend->events.new_input); } void diff --git a/src/libds/backend/wayland/backend.c b/src/libds/backend/wayland/backend.c index 778ca1c..d956aa0 100644 --- a/src/libds/backend/wayland/backend.c +++ b/src/libds/backend/wayland/backend.c @@ -14,8 +14,8 @@ static const struct ds_backend_interface wl_backend_interface; static void wl_backend_handle_display_destroy(struct wl_listener *listener, void *data); -static bool wl_backend_server_init(struct ds_wl_backend_server *server, - const char *name); +static bool wl_backend_server_init(struct ds_wl_backend *wl_backend, + struct ds_wl_backend_server *server, const char *name); static void wl_backend_server_finish(struct ds_wl_backend_server *server); static int wl_backend_handle_dispatch_events(int fd, uint32_t mask, void *data); @@ -38,8 +38,9 @@ ds_wl_backend_create(struct wl_display *display, const char *server_name) wl_backend->display = display; wl_list_init(&wl_backend->buffers); wl_list_init(&wl_backend->outputs); + wl_list_init(&wl_backend->seats); - if (!wl_backend_server_init(&wl_backend->server, server_name)) { + if (!wl_backend_server_init(wl_backend, &wl_backend->server, server_name)) { ds_err("Failed to initialize Wayland Server"); goto err_server; } @@ -48,7 +49,7 @@ ds_wl_backend_create(struct wl_display *display, const char *server_name) fd = wl_display_get_fd(wl_backend->server.display); wl_backend->server_event_source = - wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, + wl_event_loop_add_fd(loop, fd, WL_EVENT_WRITABLE | WL_EVENT_READABLE, wl_backend_handle_dispatch_events, wl_backend); if (!wl_backend->server_event_source) { ds_err("Failed to create event source"); @@ -84,6 +85,7 @@ wl_backend_destroy(struct ds_wl_backend *backend) { struct ds_wl_output *output, *tmp_output; struct ds_wl_buffer *buffer, *tmp_buffer; + struct ds_wl_seat *seat, *tmp_seat; ds_dbg("Destroy wayland backend(%p)", backend); @@ -93,6 +95,9 @@ wl_backend_destroy(struct ds_wl_backend *backend) wl_list_for_each_safe(buffer, tmp_buffer, &backend->buffers, link) destroy_wl_buffer(buffer); + wl_list_for_each_safe(seat, tmp_seat, &backend->seats, link) + destroy_wl_seat(seat); + ds_backend_finish(&backend->base); wl_list_remove(&backend->display_destroy.link); @@ -159,6 +164,7 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *iface, uint32_t version) { struct ds_wl_backend_server *server = data; + struct ds_wl_seat *seat; ds_log(DS_DBG, "Wayland global: %s v%d", iface, version); @@ -176,6 +182,15 @@ registry_handle_global(void *data, struct wl_registry *registry, server->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); wl_shm_add_listener(server->shm, &shm_listener, server); } + else if (strcmp(iface, wl_seat_interface.name) == 0) { + seat = create_wl_seat(server->backend, name, version); + if (!seat) { + ds_err("Could not create ds_wl_seat"); + return; + } + + wl_list_insert(&server->backend->seats, &seat->link); + } } static void @@ -192,8 +207,10 @@ static const struct wl_registry_listener registry_listener = }; static bool -wl_backend_server_init(struct ds_wl_backend_server *server, const char *name) +wl_backend_server_init(struct ds_wl_backend *wl_backend, struct ds_wl_backend_server *server, const char *name) { + server->backend = wl_backend; + server->display = wl_display_connect(name); if (!server->display) { ds_log_errno(DS_ERR, "Could not connect to display: name \"%s\"", name); diff --git a/src/libds/backend/wayland/backend.h b/src/libds/backend/wayland/backend.h index ab37ec0..12e594a 100644 --- a/src/libds/backend/wayland/backend.h +++ b/src/libds/backend/wayland/backend.h @@ -3,9 +3,12 @@ #include "libds/interfaces/backend.h" #include "libds/interfaces/output.h" +#include "libds/interfaces/input_device.h" +#include "libds/interfaces/pointer.h" struct ds_wl_backend_server { + struct ds_wl_backend *backend; struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; @@ -23,6 +26,7 @@ struct ds_wl_backend struct wl_list outputs; // ds_wl_output.link struct wl_list buffers; // ds_wl_buffer.link + struct wl_list seats; // ds_wl_seat.link struct wl_event_source *server_event_source; struct ds_wl_backend_server server; @@ -50,6 +54,53 @@ struct ds_wl_output struct wl_callback *frame_callback; struct wl_list link; + + struct { + struct ds_wl_pointer *pointer; + struct wl_surface *surface; + int32_t hotspot_x, hotspot_y; + uint32_t enter_serial; + } cursor; +}; + +struct ds_wl_seat +{ + struct ds_wl_backend *backend; + struct ds_wl_output *output; + + struct wl_seat *wl_seat; + char *name; + + struct ds_input_device *pointer_dev; + struct ds_input_device *keyboard_dev; + struct ds_input_device *touch_dev; + + struct wl_callback *initial_info_cb; + + struct wl_list link; // ds_wl_backend.seats + + enum wl_seat_capability caps; + + int version; + uint32_t enter_serial; + + bool initialized; +}; + +struct ds_wl_input_device +{ + struct ds_input_device base; + + struct ds_wl_backend *backend; + struct ds_wl_seat *seat; +}; + +struct ds_wl_pointer +{ + struct ds_pointer base; + + struct ds_wl_input_device *input_device; + struct wl_pointer *wl_pointer; }; struct ds_wl_backend * @@ -58,4 +109,14 @@ wl_backend_from_backend(struct ds_backend *backend); void destroy_wl_buffer(struct ds_wl_buffer *buffer); +struct ds_wl_seat *create_wl_seat(struct ds_wl_backend *backend, uint32_t id, + uint32_t available_version); + +void destroy_wl_seat(struct ds_wl_seat *seat); + +void output_enter_pointer(struct ds_wl_output *output, + struct ds_wl_pointer *pointer, uint32_t serial); + +void output_leave_pointer(struct ds_wl_output *output); + #endif diff --git a/src/libds/backend/wayland/meson.build b/src/libds/backend/wayland/meson.build index db68fe9..88574a4 100644 --- a/src/libds/backend/wayland/meson.build +++ b/src/libds/backend/wayland/meson.build @@ -1,6 +1,7 @@ libds_files += files( 'backend.c', 'output.c', + 'seat.c', ) protocols = { diff --git a/src/libds/backend/wayland/output.c b/src/libds/backend/wayland/output.c index 1966a97..36ea5f7 100644 --- a/src/libds/backend/wayland/output.c +++ b/src/libds/backend/wayland/output.c @@ -13,6 +13,8 @@ const struct ds_output_interface wl_output_iface; static const struct xdg_surface_listener wl_output_xdg_surface_listener; static const struct xdg_toplevel_listener wl_output_xdg_toplevel_listener; +static void output_update_cursor(struct ds_wl_output *output); + struct ds_output * ds_wl_backend_create_output(struct ds_backend *ds_backend) { @@ -90,6 +92,32 @@ destroy_wl_buffer(struct ds_wl_buffer *buffer) free(buffer); } +void +output_enter_pointer(struct ds_wl_output *output, + struct ds_wl_pointer *pointer, uint32_t serial) +{ + output->cursor.pointer = pointer; + output->cursor.enter_serial = serial; + + output_update_cursor(output); +} + +void +output_leave_pointer(struct ds_wl_output *output) +{ + output->cursor.pointer = NULL; + output->cursor.enter_serial = 0; +} + +static void output_update_cursor(struct ds_wl_output *output) +{ + struct ds_wl_pointer *pointer = output->cursor.pointer; + + wl_pointer_set_cursor(pointer->wl_pointer, output->cursor.enter_serial, + output->cursor.surface, output->cursor.hotspot_x, + output->cursor.hotspot_y); +} + static struct ds_wl_output * wl_output_from_output(struct ds_output *ds_output) { diff --git a/src/libds/backend/wayland/seat.c b/src/libds/backend/wayland/seat.c new file mode 100644 index 0000000..b799e66 --- /dev/null +++ b/src/libds/backend/wayland/seat.c @@ -0,0 +1,406 @@ +#include +#include +#include +#include +#include + +#include "libds/log.h" +#include "libds/pointer.h" + +#include "backend.h" + +#ifdef MIN +# undef MIN +#endif + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static const struct wl_seat_listener seat_listener; +static const struct wl_callback_listener seat_callback_listener; + +static void seat_update_capabilities(struct ds_wl_seat *seat, + enum wl_seat_capability caps); +static struct ds_input_device * +create_wl_input_device(struct ds_wl_seat *seat, + enum ds_input_device_type type); +static struct ds_pointer *create_wl_pointer(struct ds_wl_seat *seat); + +struct ds_wl_seat * +create_wl_seat(struct ds_wl_backend *backend, uint32_t id, + uint32_t available_version) +{ + struct ds_wl_seat *seat; + + seat = calloc(1, sizeof *seat); + if (!seat) + return NULL; + + seat->backend = backend; + seat->version = MIN(available_version, 5); + seat->wl_seat = wl_registry_bind(backend->server.registry, id, + &wl_seat_interface, seat->version); + + wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + + seat->initial_info_cb = wl_display_sync(backend->server.display); + wl_callback_add_listener(seat->initial_info_cb, &seat_callback_listener, + seat); + + ds_dbg("wl_backend: Seat(%p) created", seat); + + return seat; +} + +void +destroy_wl_seat(struct ds_wl_seat *seat) +{ + ds_dbg("wl_backend: Seat(%p) destroy", seat); + + if (seat->pointer_dev) + ds_input_device_destroy(seat->pointer_dev); + + if (seat->keyboard_dev) + ds_input_device_destroy(seat->keyboard_dev); + + if (seat->touch_dev) + ds_input_device_destroy(seat->touch_dev); + + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_seat_release(seat->wl_seat); + else + wl_seat_destroy(seat->wl_seat); + + wl_list_remove(&seat->link); + + free(seat->name); + free(seat); +} + +static void +seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) +{ + struct ds_wl_seat *seat = data; + + if (seat->initialized) + seat_update_capabilities(seat, caps); + else + seat->caps = caps; + + ds_dbg("wl_backend: Seat(%p) capabilities(%d)", seat, caps); +} + +static void +seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) +{ + struct ds_wl_seat *seat = data; + + if (seat->name) + free(seat->name); + + ds_dbg("wl_backend: Seat(%p) name(%s)", seat, name); + + seat->name = strdup(name); +} + +static const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + +static void +seat_add_callback_handle_done(void *data, struct wl_callback *callback, + uint32_t callback_data) +{ + struct ds_wl_seat *seat = data; + + wl_callback_destroy(seat->initial_info_cb); + seat->initial_info_cb = NULL; + seat->initialized = true; + + seat_update_capabilities(seat, seat->caps); +} + +static const struct wl_callback_listener seat_callback_listener = { + .done = seat_add_callback_handle_done, +}; + +static void +seat_update_capabilities(struct ds_wl_seat *seat, enum wl_seat_capability caps) +{ + if ((caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer_dev == NULL) { + ds_dbg("wl_backend: Seat(%p) offered pointer", seat); + + seat->pointer_dev = create_wl_input_device(seat, + DS_INPUT_DEVICE_POINTER); + seat->pointer_dev->pointer = create_wl_pointer(seat); + + wl_signal_emit(&seat->backend->base.events.new_input, + seat->pointer_dev); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && + seat->pointer_dev != NULL) { + ds_dbg("wl_backend: Seat(%p) dropped pointer", seat); + ds_input_device_destroy(seat->pointer_dev); + seat->pointer_dev = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard_dev == NULL) { + ds_dbg("wl_backend: Seat(%p) offered keyboard", seat); + + seat->keyboard_dev = create_wl_input_device(seat, + DS_INPUT_DEVICE_KEYBOARD); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && + seat->keyboard_dev != NULL) { + ds_dbg("wl_backend: Seat(%p) dropped keyboard", seat); + ds_input_device_destroy(seat->keyboard_dev); + seat->keyboard_dev = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch_dev == NULL) { + ds_dbg("wl_backend: Seat(%p) offered touch", seat); + seat->touch_dev = create_wl_input_device(seat, + DS_INPUT_DEVICE_TOUCH); + } + else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && + seat->touch_dev != NULL) { + ds_dbg("wl_backend: Seat(%p) dropped touch", seat); + ds_input_device_destroy(seat->touch_dev); + seat->touch_dev = NULL; + } +} + +static const struct ds_input_device_interface input_device_iface; + +static bool +ds_input_device_is_wl(struct ds_input_device *ds_dev) +{ + return ds_dev->iface == &input_device_iface; +} + +static struct ds_wl_input_device * +get_wl_input_device_from_input_device(struct ds_input_device *ds_dev) +{ + assert(ds_input_device_is_wl(ds_dev)); + return (struct ds_wl_input_device *)ds_dev; +} + +static void +input_device_iface_destroy(struct ds_input_device *ds_dev) +{ + struct ds_wl_input_device *dev; + + dev = get_wl_input_device_from_input_device(ds_dev); + + free(dev); +} + +static const struct ds_input_device_interface input_device_iface = +{ + .destroy = input_device_iface_destroy, +}; + +static struct ds_input_device * +create_wl_input_device(struct ds_wl_seat *seat, + enum ds_input_device_type type) +{ + struct ds_wl_input_device *dev; + unsigned int vendor = 0, product = 0; + size_t name_size; + char *name; + + dev = calloc(1, sizeof *dev); + if (!dev) + return NULL; + + dev->backend = seat->backend; + dev->seat = seat; + + name_size = 8 + strlen(seat->name) + 1; + name = alloca(name_size); + (void) snprintf(name, name_size, "wayland-%s", seat->name); + + ds_input_device_init(&dev->base, type, &input_device_iface, name, vendor, + product); + + return &dev->base; +} + +static const struct ds_pointer_interface pointer_iface; + +static struct ds_wl_pointer * +get_wl_pointer_from_pointer(struct ds_pointer *ds_pointer) +{ + assert(ds_pointer->iface == &pointer_iface); + return (struct ds_wl_pointer *)ds_pointer; +} + +static void +pointer_iface_destroy(struct ds_pointer *ds_pointer) +{ + struct ds_wl_pointer *pointer; + + pointer = get_wl_pointer_from_pointer(ds_pointer); + + wl_pointer_release(pointer->wl_pointer); + + free(pointer); +} + +static const struct ds_pointer_interface pointer_iface = { + .destroy = pointer_iface_destroy, +}; + +static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + struct ds_wl_seat *seat = data; + struct ds_wl_pointer *pointer; + + if (!surface) + return; + + ds_dbg("Enter pointer"); + + seat->output = wl_surface_get_user_data(surface); + seat->enter_serial = serial; + + pointer = get_wl_pointer_from_pointer(seat->pointer_dev->pointer); + output_enter_pointer(seat->output, pointer, seat->enter_serial); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) +{ + struct ds_wl_seat *seat = data; + struct ds_wl_output *output; + + if (!seat->output) + return; + + output = wl_surface_get_user_data(surface); + if (seat->output != output) + return; + + ds_dbg("Leave pointer"); + + output_leave_pointer(seat->output); + + seat->output = NULL; + seat->enter_serial = 0; +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + struct ds_wl_seat *seat = data; + + if (!seat->output) + return; + + // FIXME take size size of a output into account + struct ds_event_pointer_motion_absolute event = { + .device = seat->pointer_dev, + .time_msec = time, + .x = wl_fixed_to_double(sx) / 700, + .y = wl_fixed_to_double(sy) / 400, + }; + + wl_signal_emit(&seat->pointer_dev->pointer->events.motion_absolute, + &event); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) +{ + struct ds_wl_seat *seat = data; + + if (!seat->output) + return; + + struct ds_event_pointer_button event = { + .device = seat->pointer_dev, + .button = button, + .state = state, + .time_msec = time, + }; + + wl_signal_emit(&seat->pointer_dev->pointer->events.button, &event); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + // TODO +} + +static void +pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) +{ + struct ds_wl_seat *seat = data; + + if (!seat->output) + return; + + wl_signal_emit(&seat->pointer_dev->pointer->events.frame, + seat->pointer_dev); +} + +static void +pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) +{ + // TODO +} + +static void +pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) +{ + // TODO +} + +static void +pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) +{ + // TODO +} + +static const struct wl_pointer_listener wl_pointer_listener = { + .enter = pointer_handle_enter, + .leave = pointer_handle_leave, + .motion = pointer_handle_motion, + .button = pointer_handle_button, + .axis = pointer_handle_axis, + .frame = pointer_handle_frame, + .axis_source = pointer_handle_axis_source, + .axis_stop = pointer_handle_axis_stop, + .axis_discrete = pointer_handle_axis_discrete, +}; + +static struct ds_pointer * +create_wl_pointer(struct ds_wl_seat *seat) +{ + struct ds_wl_pointer *pointer; + + pointer = calloc(1, sizeof *pointer); + if (!pointer) { + ds_err("Could not allocate memory"); + return NULL; + } + + ds_pointer_init(&pointer->base, &pointer_iface); + + pointer->wl_pointer = wl_seat_get_pointer(seat->wl_seat); + wl_pointer_add_listener(pointer->wl_pointer, &wl_pointer_listener, seat); + + return &pointer->base; +} diff --git a/src/libds/input_device.c b/src/libds/input_device.c new file mode 100644 index 0000000..db84100 --- /dev/null +++ b/src/libds/input_device.c @@ -0,0 +1,69 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +#include "libds/log.h" +#include "libds/interfaces/input_device.h" +#include "libds/interfaces/pointer.h" + +WL_EXPORT enum ds_input_device_type +ds_input_device_get_type(struct ds_input_device *dev) +{ + return dev->type; +} + +WL_EXPORT struct ds_pointer * +ds_input_device_get_pointer(struct ds_input_device *dev) +{ + if (dev->type != DS_INPUT_DEVICE_POINTER) { + ds_err("Given ds_input_device is not a pointer device"); + return NULL; + } + + return dev->pointer; +} + +WL_EXPORT void +ds_input_device_add_destroy_listener(struct ds_input_device *dev, + struct wl_listener *listener) +{ + wl_signal_add(&dev->events.destroy, listener); +} + +void +ds_input_device_init(struct ds_input_device *dev, + enum ds_input_device_type type, + const struct ds_input_device_interface *iface, + const char *name, int vendor, int product) +{ + dev->type = type; + dev->iface = iface; + dev->name = strdup(name); + + wl_signal_init(&dev->events.destroy); +} + +void +ds_input_device_destroy(struct ds_input_device *dev) +{ + wl_signal_emit(&dev->events.destroy, dev); + + if (dev->_device) { + switch (dev->type) { + case DS_INPUT_DEVICE_POINTER: + ds_pointer_destroy(dev->pointer); + break; + default: + ds_err("Warning: leaking memory %p %p %d", + dev->_device, dev, dev->type); + break; + } + } + + free(dev->name); + if (dev->iface && dev->iface->destroy) + dev->iface->destroy(dev); + else + free(dev); +} diff --git a/src/libds/meson.build b/src/libds/meson.build index 50f7962..a08dfdc 100644 --- a/src/libds/meson.build +++ b/src/libds/meson.build @@ -18,6 +18,8 @@ libds_files = [ 'xdg_shell/xdg_toplevel.c', 'pixel_format.c', 'backend.c', + 'input_device.c', + 'pointer.c', ] protocols = { diff --git a/src/libds/pointer.c b/src/libds/pointer.c new file mode 100644 index 0000000..5c5cbda --- /dev/null +++ b/src/libds/pointer.c @@ -0,0 +1,55 @@ +#include +#include +#include "libds/interfaces/pointer.h" + +void +ds_pointer_init(struct ds_pointer *pointer, + const struct ds_pointer_interface *iface) +{ + pointer->iface = iface; + + wl_signal_init(&pointer->events.motion); + wl_signal_init(&pointer->events.motion_absolute); + wl_signal_init(&pointer->events.button); + wl_signal_init(&pointer->events.frame); +} + +void +ds_pointer_destroy(struct ds_pointer *pointer) +{ + if (!pointer) + return; + + if (pointer->iface && pointer->iface->destroy) + pointer->iface->destroy(pointer); + else + free(pointer); +} + +WL_EXPORT void +ds_pointer_add_motion_listener(struct ds_pointer *pointer, + struct wl_listener *listener) +{ + wl_signal_add(&pointer->events.motion, listener); +} + +WL_EXPORT void +ds_pointer_add_motion_absolute_listener(struct ds_pointer *pointer, + struct wl_listener *listener) +{ + wl_signal_add(&pointer->events.motion_absolute, listener); +} + +WL_EXPORT void +ds_pointer_add_button_listener(struct ds_pointer *pointer, + struct wl_listener *listener) +{ + wl_signal_add(&pointer->events.button, listener); +} + +WL_EXPORT void +ds_pointer_add_frame_listener(struct ds_pointer *pointer, + struct wl_listener *listener) +{ + wl_signal_add(&pointer->events.frame, listener); +} -- 2.7.4