From: Changyeon Lee Date: Tue, 16 Aug 2022 07:34:36 +0000 (+0900) Subject: merge tinyds-tdm-hwc code to tinyds-tdm X-Git-Tag: accepted/tizen/unified/20220821.211122~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0073e07742b9137f228fd62c7aeea1f7cef755e0;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git merge tinyds-tdm-hwc code to tinyds-tdm Change-Id: I15e9fd39f646b8fd7fd75ae4b957504a42b69c88 --- diff --git a/examples/meson.build b/examples/meson.build index 3370f26..899529e 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -37,21 +37,3 @@ executable('tinyds-tdm', install_dir: libds_tizen_bindir, install : true ) - -tinyds_tdm_hwc_files = [ - 'tinyds-tdm-hwc.c', - 'pixman-helper.c', - 'pixman-tbm-helper.c', - 'tinyds-tdm-renderer.c', -] -executable('tinyds-tdm-hwc', - tinyds_tdm_hwc_files, - dependencies: [ - common_deps, - deps_libds_tizen_backend_tdm, - dependency('pixman-1', required: true), - dependency('threads', required: true), - ], - install_dir: libds_tizen_bindir, - install : true -) diff --git a/examples/tinyds-tdm-hwc.c b/examples/tinyds-tdm-hwc.c deleted file mode 100644 index 46925f1..0000000 --- a/examples/tinyds-tdm-hwc.c +++ /dev/null @@ -1,768 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#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 "pixman-helper.h" - -#define TINYDS_UNUSED __attribute__((unused)) - -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; - struct wl_listener output_frame; - - int width, height; - - struct wl_event_source *idle_commit; - bool commitable; - bool damaged; - - struct ds_tdm_output_hwc *hwc; -}; - -struct tinyds_server -{ - struct ds_tbm_server *tbm_server; - - struct wl_display *display; - - struct ds_backend *backend; - struct ds_compositor *compositor; - struct ds_xdg_shell *xdg_shell; - - struct tinyds_output *output; - struct wl_event_source *stdin_source; - - struct wl_list views; - - struct wl_listener new_output; - struct wl_listener new_xdg_surface; -}; - -struct tinyds_view -{ - struct tinyds_server *server; - - struct tinyds_texture *texture; - struct ds_xdg_surface *xdg_surface; - - struct wl_listener xdg_surface_map; - struct wl_listener xdg_surface_unmap; - struct wl_listener xdg_surface_destroy; - struct wl_listener surface_commit; - struct wl_list link; // tinyds_server::views - - struct ds_tdm_output_hwc_window *hwc_window; - - int x, y; - bool mapped; -}; - -struct tinyds_server tinyds; - -static bool init_server(struct tinyds_server *server, struct wl_display *display); -static int server_dispatch_stdin(int fd, uint32_t mask, void *data); -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); -static void output_hwc_init(struct tinyds_output *output); -static void output_schedule_commit(struct tinyds_output *output); -static void output_commit(struct tinyds_output *output); -#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, - int width, int height, uint32_t format); -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) -{ - struct tinyds_server *server = &tinyds; - struct wl_display *display; - struct wl_event_loop *loop; - const char *socket; - bool res; - - ds_log_init(DS_INF, NULL); - - display = wl_display_create(); - assert(display); - - res = init_server(server, display); - assert(res); - - socket = wl_display_add_socket_auto(display); - assert(socket); - - ds_backend_start(server->backend); - - setenv("WAYLAND_DISPLAY", socket, true); - - ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); - - loop = wl_display_get_event_loop(display); - server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO, - WL_EVENT_READABLE, server_dispatch_stdin, server); - - wl_display_run(display); - - wl_display_destroy_clients(display); - wl_display_destroy(display); - - return 0; -} - -static void -view_handle_xdg_surface_map(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, xdg_surface_map); - view->mapped = true; -} - -static void -view_handle_xdg_surface_unmap(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, xdg_surface_unmap); - view->mapped = false; -} - -static void -view_handle_xdg_surface_destroy(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, xdg_surface_destroy); - - draw_server_with_damage(view->server); - - ds_tdm_output_hwc_window_destroy(view->hwc_window); - - wl_list_remove(&view->xdg_surface_destroy.link); - wl_list_remove(&view->xdg_surface_map.link); - wl_list_remove(&view->xdg_surface_unmap.link); - wl_list_remove(&view->surface_commit.link); - wl_list_remove(&view->link); - free(view); -} - -static void -view_handle_surface_commit(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, surface_commit); - - draw_server_with_damage(view->server); -} - -static void -server_new_xdg_surface(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct tinyds_view *view; - struct ds_xdg_surface *xdg_surface; - - server = wl_container_of(listener, server, new_xdg_surface); - xdg_surface = data; - - ds_inf("New xdg_surface(%p)", (void *)xdg_surface); - - view = calloc(1, sizeof *view); - assert(view); - - view->server = server; - view->xdg_surface = xdg_surface; - - view->xdg_surface_map.notify = view_handle_xdg_surface_map; - ds_xdg_surface_add_map_listener(xdg_surface, - &view->xdg_surface_map); - - view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap; - ds_xdg_surface_add_unmap_listener(xdg_surface, - &view->xdg_surface_unmap); - - view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy; - ds_xdg_surface_add_destroy_listener(xdg_surface, - &view->xdg_surface_destroy); - - view->surface_commit.notify = view_handle_surface_commit; - ds_surface_add_commit_listener( - ds_xdg_surface_get_surface(xdg_surface), - &view->surface_commit); - - view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc); - - wl_list_insert(server->views.prev, &view->link); -} - -static void -backend_handle_new_output(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct tinyds_output *output; - struct ds_output *ds_output; - const struct ds_output_mode *mode; - - server = wl_container_of(listener, server, new_output); - ds_output = data; - - ds_inf("New output(%p)", ds_output); - - if (server->output) - return; - - mode = ds_output_get_preferred_mode(ds_output); - ds_output_set_mode(ds_output, mode); - - output = calloc(1, sizeof *output); - if (!output) - return; - - output->server = server; - output->ds_output = ds_output; - output->width = mode->width; - output->height = mode->height; - output->damaged = true; - output->commitable = true; - -#ifdef USE_TDM_BUFFER_QUEUE - output_buffer_queue_init(output); - output_renderer_init(output); -#else - output_swapchain_init(output, mode->width, mode->height, - DRM_FORMAT_XRGB8888); -#endif - - output_hwc_init(output); - - output->output_destroy.notify = output_handle_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); - - server->output = output; - - output_schedule_commit(output); -} - -static bool -init_server(struct tinyds_server *server, struct wl_display *display) -{ - server->display = display; - - wl_list_init(&server->views); - - if (wl_display_init_shm(display) != 0) - return false; - - server->backend = ds_tdm_backend_create(display); - if (!server->backend) - return false; - - server->new_output.notify = backend_handle_new_output; - ds_backend_add_new_output_listener(server->backend, - &server->new_output); - - server->compositor = ds_compositor_create(display); - if (!server->compositor) { - ds_backend_destroy(server->backend); - 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); - return false; - } - - server->new_xdg_surface.notify = server_new_xdg_surface; - ds_xdg_shell_add_new_surface_listener(server->xdg_shell, - &server->new_xdg_surface); - - return true; -} - -static void -output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_output *output = - wl_container_of(listener, output, output_destroy); - - wl_list_remove(&output->output_destroy.link); - wl_list_remove(&output->output_frame.link); - - 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); - - output->server->output = NULL; - - free(output); -} -static void -output_commit(struct tinyds_output *output) -{ - uint32_t num_changed = 0; - uint32_t num_windows = 0, current_num_windows = 0; - struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL; - struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL; - enum ds_tdm_output_hwc_window_composition composition; - struct tinyds_view *view; - int i; - bool need_target = false; - - if (!output->commitable || !output->damaged) - return; - - wl_list_for_each_reverse(view, &output->server->views, link) { - if (!view->hwc_window) - continue; - - if (view->mapped) - num_windows++; - } - - if (num_windows) { - composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows); - if (!composited_hwc_windows) - return; - } - - wl_list_for_each_reverse(view, &output->server->views, link) { - struct ds_buffer *ds_buffer; - struct ds_tdm_box src_box; - int w = 0, h = 0; - - if (!view->hwc_window) - continue; - - ds_buffer = ds_surface_get_buffer( - ds_xdg_surface_get_surface(view->xdg_surface)); - if (!ds_buffer) - continue; - - ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer); - - if (ds_buffer) - ds_buffer_get_size(ds_buffer, &w, &h); - - src_box.x = 0; - src_box.y = 0; - src_box.width = w; - src_box.height = h; - - ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box); - ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y); - ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h); - ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL); - - if (view->mapped) { - ds_tdm_output_hwc_window_set_composition(view->hwc_window, - DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE); - - composited_hwc_windows[current_num_windows] = view->hwc_window; - current_num_windows++; - } else { - ds_tdm_output_hwc_window_set_composition(view->hwc_window, - DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE); - } - } - - if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows, - num_windows, &num_changed)) { - free(composited_hwc_windows); - ds_err("Could not hwc validate"); - return; - } - - if (composited_hwc_windows) - free(composited_hwc_windows); - - if (num_changed > 0) { - changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows); - if (!changed_hwc_windows) - return; - - if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed, - changed_hwc_windows)) { - ds_err("Could not get chaged composition"); - return; - } - - for (i = 0; i < num_changed; i++) { - composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]); - if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) { - need_target = true; - break; - } - } - } - - if (changed_hwc_windows) - free(changed_hwc_windows); - - if (!ds_tdm_output_hwc_accept_validation(output->hwc)) { - ds_err("Could not hwc accept validateion"); - return; - } - - if (need_target) - draw_output(output); - -#ifdef USE_TDM_BUFFER_QUEUE - struct ds_buffer *buffer; - - buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue); - if (buffer) - output_swap_buffer(output, buffer); -#endif - - ds_output_commit(output->ds_output); - - output->commitable = false; - output->damaged = false; - - wl_list_for_each(view, &output->server->views, link) { - enum ds_tdm_output_hwc_window_composition composition; - - if (!view->mapped) - continue; - - composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); - if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) - view_send_frame_done(view); - } - - ds_inf("output:%p commit", output); -} - -static void -output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_output *output = - wl_container_of(listener, output, output_frame); - - ds_inf("output:%p handle frame", output); - - output->commitable = true; - - output_commit(output); -} - -static void -draw_server_with_damage(struct tinyds_server *server) -{ - server->output->damaged = true; - output_schedule_commit(server->output); -} - -static void -output_hwc_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->hwc = ds_tdm_output_get_hwc(tdm_output); - assert(output->hwc); - - ds_tdm_output_hwc_set_enabled(output->hwc, true); -} - -#ifdef USE_TDM_BUFFER_QUEUE -static void -output_handle_buffer_queue_acquirable(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_output *output; - - output = wl_container_of(listener, output, buffer_queue_acquirable); - - draw_server_with_damage(output->server); -} - -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, 0, 0, 0); -} - -static void -output_draw_with_renderer(struct tinyds_output *output) -{ - struct tinyds_view *view; - - ds_dbg(">> BEGIN UPDATE TEXTURES"); - - wl_list_for_each(view, &output->server->views, link) { - struct ds_buffer *ds_buffer; - struct ds_tbm_client_buffer *tbm_buffer; - tbm_surface_h surface; - enum ds_tdm_output_hwc_window_composition composition; - - if (!view->mapped) - continue; - - composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); - if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) - continue; - - ds_buffer = ds_surface_get_buffer( - ds_xdg_surface_get_surface(view->xdg_surface)); - assert(ds_buffer); - - tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); - assert(tbm_buffer); - - surface = ds_tbm_client_buffer_get_tbm_surface(tbm_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, - int width, int height, uint32_t format) - -{ - output->allocator = ds_tbm_allocator_create(); - assert(output->allocator); - - output->swapchain = ds_swapchain_create(output->allocator, - width, height, format); - 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; - enum ds_tdm_output_hwc_window_composition composition; - - output_buffer = ds_swapchain_acquire(output->swapchain, NULL); - if (!output_buffer) - return; - - output_image = pixman_image_from_buffer(output_buffer, - DS_BUFFER_DATA_PTR_ACCESS_WRITE); - if (!output_image) { - ds_buffer_unlock(output_buffer); - return; - } - - pixman_image_fill_color(output_image, 0, 0, 0); - - wl_list_for_each(view, &output->server->views, link) { - if (!view->mapped) - continue; - - composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); - if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || - (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) - continue; - - draw_view(view, output_image); - } - pixman_image_unref(output_image); - - output_swap_buffer(output, output_buffer); -} - -static void -draw_view(struct tinyds_view *view, pixman_image_t *dst_image) -{ - struct ds_buffer *buffer; - pixman_image_t *src_image; - - buffer = ds_surface_get_buffer( - ds_xdg_surface_get_surface(view->xdg_surface)); - if (!buffer) - return; - - src_image = pixman_image_from_buffer(buffer, - DS_BUFFER_DATA_PTR_ACCESS_READ); - pixman_image_composite32(PIXMAN_OP_OVER, - src_image, - NULL, - dst_image, - 0, 0, 0, 0, - view->x, view->y, - pixman_image_get_width(src_image), - pixman_image_get_height(src_image)); - pixman_image_unref(src_image); - - view_send_frame_done(view); -} -#endif - -static void -draw_output(struct tinyds_output *output) -{ -#ifdef USE_TDM_BUFFER_QUEUE - output_draw_with_renderer(output); -#else - output_draw_with_swapchain(output); -#endif - - ds_inf("output:%p draw", output); -} - -static void -output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer) -{ - ds_output_attach_buffer(output->ds_output, buffer); - - 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 void -output_schedule_commit_handle_idle_timer(void *data) -{ - struct tinyds_output *output = data; - output->idle_commit = NULL; - - output_commit(output); -} - -static void -output_schedule_commit(struct tinyds_output *output) -{ - if (output->idle_commit) - return; - - output->damaged = true; - - struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display); - output->idle_commit = - wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output); -} - -static int -server_dispatch_stdin(int fd, uint32_t mask, void *data) -{ - struct tinyds_server *server = data; - - wl_display_terminate(server->display); - - return 1; -} diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 2158bac..e8416ab 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -27,6 +27,7 @@ #include #include #include +#include #define USE_TDM_BUFFER_QUEUE @@ -62,8 +63,13 @@ struct tinyds_output int width, height; - bool drawable; + struct wl_event_source *idle_commit; + bool committable; bool damaged; + bool target_updated; + + struct ds_tdm_output_hwc *hwc; + struct ds_tdm_output_hwc_window *bg_hwc_window; }; struct tinyds_dpms @@ -127,6 +133,8 @@ struct tinyds_view struct wl_listener surface_commit; struct wl_list link; // tinyds_server::views + struct ds_tdm_output_hwc_window *hwc_window; + int x, y; bool mapped; @@ -180,6 +188,9 @@ 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); +static void output_hwc_init(struct tinyds_output *output); +static void output_schedule_commit(struct tinyds_output *output); +static void output_commit(struct tinyds_output *output); #ifdef USE_TDM_BUFFER_QUEUE static void output_buffer_queue_init(struct tinyds_output *output); static void output_renderer_init(struct tinyds_output *output); @@ -302,10 +313,12 @@ 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); - server = view->server; + + draw_server_with_damage(view->server); + + ds_tdm_output_hwc_window_destroy(view->hwc_window); wl_list_remove(&view->xdg_surface_destroy.link); wl_list_remove(&view->xdg_surface_map.link); @@ -313,8 +326,6 @@ 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 @@ -362,11 +373,14 @@ server_new_xdg_surface(struct wl_listener *listener, void *data) ds_xdg_surface_get_surface(xdg_surface), &view->surface_commit); - wl_list_insert(server->views.prev, &view->link); - view->x = rand() % 1000; view->y = rand() % 500; + view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc); + assert(view->hwc_window); + + wl_list_insert(server->views.prev, &view->link); + view->pid = 0; view->effect_type = -1; @@ -380,6 +394,7 @@ backend_handle_new_output(struct wl_listener *listener, void *data) struct tinyds_output *output; struct ds_output *ds_output; const struct ds_output_mode *mode; + struct ds_tdm_box src_box; server = wl_container_of(listener, server, new_output); ds_output = data; @@ -400,8 +415,10 @@ backend_handle_new_output(struct wl_listener *listener, void *data) output->ds_output = ds_output; output->width = mode->width; output->height = mode->height; - output->drawable = true; output->damaged = true; + output->committable = true; + + output_hwc_init(output); #ifdef USE_TDM_BUFFER_QUEUE output_buffer_queue_init(output); @@ -411,6 +428,19 @@ backend_handle_new_output(struct wl_listener *listener, void *data) DRM_FORMAT_XRGB8888); #endif + output->bg_hwc_window = ds_tdm_output_hwc_window_create(output->hwc); + assert(output->bg_hwc_window); + + src_box.x = 0; + src_box.y = 0; + src_box.width = output->width; + src_box.height = output->height; + + ds_tdm_output_hwc_window_set_src_box(output->bg_hwc_window, &src_box); + ds_tdm_output_hwc_window_set_position(output->bg_hwc_window, 0, 0); + ds_tdm_output_hwc_window_set_dest_size(output->bg_hwc_window, output->width, output->height); + ds_tdm_output_hwc_window_set_transform(output->bg_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL); + output->output_destroy.notify = output_handle_destroy; ds_output_add_destroy_listener(ds_output, &output->output_destroy); @@ -421,7 +451,7 @@ backend_handle_new_output(struct wl_listener *listener, void *data) server->output = output; - draw_output(output); + output_schedule_commit(output); } static bool @@ -799,6 +829,9 @@ output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) struct tinyds_output *output = wl_container_of(listener, output, output_destroy); + if (output->bg_hwc_window) + ds_tdm_output_hwc_window_destroy(output->bg_hwc_window); + wl_list_remove(&output->output_destroy.link); wl_list_remove(&output->output_frame.link); @@ -823,20 +856,213 @@ output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) } static void +output_commit(struct tinyds_output *output) +{ + uint32_t num_changed = 0; + uint32_t num_windows = 0, current_num_windows = 0; + struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL; + struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL; + enum ds_tdm_output_hwc_window_composition composition; + struct tinyds_view *view; + int i; + bool need_target = false; + bool fully_obscured = false; + struct ds_buffer *ds_buffer; + struct ds_tdm_box src_box; + int w = 0, h = 0; + + if (!output->committable) + return; + + if (!output->damaged && !output->target_updated) + return; + + wl_list_for_each_reverse(view, &output->server->views, link) { + if (!view->hwc_window) + continue; + + ds_buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + if (!ds_buffer) + continue; + + if (!view->mapped) + continue; + + num_windows++; + + ds_buffer_get_size(ds_buffer, &w, &h); + + if ((output->width <= w) && (output->height <= h)) + fully_obscured = true; + } + + if (fully_obscured) { + ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE); + } else { + ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT); + num_windows++; + need_target = true; + } + + if (num_windows) { + composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows); + if (!composited_hwc_windows) + return; + + wl_list_for_each_reverse(view, &output->server->views, link) { + if (!view->hwc_window) + continue; + + ds_buffer = ds_surface_get_buffer( + ds_xdg_surface_get_surface(view->xdg_surface)); + if (!ds_buffer) + continue; + + ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer); + + ds_buffer_get_size(ds_buffer, &w, &h); + + src_box.x = 0; + src_box.y = 0; + src_box.width = w; + src_box.height = h; + + ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box); + ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y); + ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h); + ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL); + + if (view->mapped) { + ds_tdm_output_hwc_window_set_composition(view->hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE); + + composited_hwc_windows[current_num_windows] = view->hwc_window; + current_num_windows++; + } else { + ds_tdm_output_hwc_window_set_composition(view->hwc_window, + DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE); + } + } + + if (!fully_obscured) { + composited_hwc_windows[current_num_windows] = output->bg_hwc_window; + current_num_windows++; + } + } + + if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows, + num_windows, &num_changed)) { + free(composited_hwc_windows); + ds_err("Could not hwc validate"); + return; + } + + if (composited_hwc_windows) + free(composited_hwc_windows); + + if (num_changed > 0) { + changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows); + if (!changed_hwc_windows) + return; + + if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed, + changed_hwc_windows)) { + free(changed_hwc_windows); + ds_err("Could not get chaged composition"); + return; + } + + for (i = 0; i < num_changed; i++) { + composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]); + if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) { + need_target = true; + break; + } + } + } + + if (changed_hwc_windows) + free(changed_hwc_windows); + + if (need_target && output->damaged) + draw_output(output); + +#ifdef USE_TDM_BUFFER_QUEUE + struct ds_buffer *buffer; + + buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue); + if (buffer) { + if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, buffer)) { + ds_err("Could not set hwc client target buffer"); + return; + } + + output_swap_buffer(output, buffer); + } +#endif + + if (!ds_tdm_output_hwc_accept_validation(output->hwc)) { + ds_err("Could not hwc accept validateion"); + return; + } + + ds_output_commit(output->ds_output); + + output->committable = false; + output->damaged = false; + output->target_updated = false; + + wl_list_for_each(view, &output->server->views, link) { + enum ds_tdm_output_hwc_window_composition composition; + + if (!view->mapped) + continue; + + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + view_send_frame_done(view); + } + + ds_dbg("output:%p commit", output); +} + +static void output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED) { struct tinyds_output *output = wl_container_of(listener, output, output_frame); - output->drawable = true; - draw_output(output); + ds_dbg("output:%p handle frame", output); + + output->committable = true; + + output_commit(output); } static void draw_server_with_damage(struct tinyds_server *server) { server->output->damaged = true; - draw_output(server->output); + output_schedule_commit(server->output); +} + +static void +output_hwc_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->hwc = ds_tdm_output_get_hwc(tdm_output); + assert(output->hwc); + + ds_tdm_output_hwc_set_enabled(output->hwc, true); } #ifdef USE_TDM_BUFFER_QUEUE @@ -845,14 +1071,11 @@ 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); + output->target_updated = true; + output_schedule_commit(output); } static void @@ -894,18 +1117,29 @@ output_draw_with_renderer(struct tinyds_output *output) struct ds_buffer *ds_buffer; struct ds_tbm_client_buffer *tbm_buffer; tbm_surface_h surface; + enum ds_tdm_output_hwc_window_composition composition; if (!view->mapped) continue; + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + continue; + ds_buffer = ds_surface_get_buffer( ds_xdg_surface_get_surface(view->xdg_surface)); - assert(ds_buffer); + if (!ds_buffer) + continue; tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); - assert(tbm_buffer); + if (!tbm_buffer) + continue; surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer); + if (!surface) + continue; renderer_add_texture(&output->renderer, surface, view->x, view->y); @@ -915,12 +1149,11 @@ output_draw_with_renderer(struct tinyds_output *output) ds_dbg("<< END UPDATE TEXTURES"); renderer_draw(&output->renderer); - } #else static void output_swapchain_init(struct tinyds_output *output, - int width, int height, uint32_t format); + int width, int height, uint32_t format) { output->allocator = ds_tbm_allocator_create(); @@ -937,6 +1170,7 @@ output_draw_with_swapchain(struct tinyds_output *output) struct tinyds_view *view; struct ds_buffer *output_buffer; pixman_image_t *output_image; + enum ds_tdm_output_hwc_window_composition composition; output_buffer = ds_swapchain_acquire(output->swapchain, NULL); if (!output_buffer) @@ -954,10 +1188,23 @@ output_draw_with_swapchain(struct tinyds_output *output) wl_list_for_each(view, &output->server->views, link) { if (!view->mapped) continue; + + composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window); + if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) || + (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR)) + continue; + draw_view(view, output_image); } pixman_image_unref(output_image); + if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, output_buffer)) { + ds_err("Could not set hwc client target buffer"); + ds_buffer_unlock(output_buffer); + return; + } + output_swap_buffer(output, output_buffer); } @@ -991,25 +1238,19 @@ draw_view(struct tinyds_view *view, pixman_image_t *dst_image) 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; + ds_dbg("output:%p draw", output); } 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); @@ -1460,3 +1701,24 @@ server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev) ds_inf("Pointer(%p) added", pointer); } + + +static void +output_schedule_commit_handle_idle_timer(void *data) +{ + struct tinyds_output *output = data; + output->idle_commit = NULL; + + output_commit(output); +} + +static void +output_schedule_commit(struct tinyds_output *output) +{ + if (output->idle_commit) + return; + + struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display); + output->idle_commit = + wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output); +} diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 8b36016..09fbf34 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -309,7 +309,6 @@ ninja -C builddir install %{_libdir}/libds-tizen-backend-tdm.so %{_bindir}/tdm-backend %{_bindir}/tinyds-tdm -%{_bindir}/tinyds-tdm-hwc %{_bindir}/ds-simple-tbm %files tbm-server