merge tinyds-tdm-hwc code to tinyds-tdm 57/279757/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Tue, 16 Aug 2022 07:34:36 +0000 (16:34 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Wed, 17 Aug 2022 07:44:36 +0000 (16:44 +0900)
Change-Id: I15e9fd39f646b8fd7fd75ae4b957504a42b69c88

examples/meson.build
examples/tinyds-tdm-hwc.c [deleted file]
examples/tinyds-tdm.c
packaging/libds-tizen.spec

index 3370f26..899529e 100644 (file)
@@ -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 (file)
index 46925f1..0000000
+++ /dev/null
@@ -1,768 +0,0 @@
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <time.h>
-
-#include <drm_fourcc.h>
-#include <pixman.h>
-#include <wayland-server.h>
-#include <libds/log.h>
-#include <libds/backend.h>
-#include <libds/output.h>
-#include <libds/compositor.h>
-#include <libds/xdg_shell.h>
-#include <libds-tizen/allocator/tbm.h>
-#include <libds-tizen/backend/tdm.h>
-#include <libds-tizen/tbm_server.h>
-#include <libds-tizen/backend/tdm_output_hwc.h>
-
-#define USE_TDM_BUFFER_QUEUE
-
-#ifdef USE_TDM_BUFFER_QUEUE
-#include "pixman-tbm-helper.h"
-#include "tinyds-tdm-renderer.h"
-#else
-#include <libds/swapchain.h>
-#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;
-}
index 2158bac..e8416ab 100644 (file)
@@ -27,6 +27,7 @@
 #include <xkbcommon/xkbcommon.h>
 #include <libds/interfaces/keyboard.h>
 #include <libds-tizen/launch.h>
+#include <libds-tizen/backend/tdm_output_hwc.h>
 
 #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);
+}
index 8b36016..09fbf34 100644 (file)
@@ -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