headless-server::output : Support display 68/207168/1
authorSung-Jin Park <sj76.park@samsung.com>
Tue, 14 May 2019 02:55:10 +0000 (11:55 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Thu, 30 May 2019 08:33:42 +0000 (17:33 +0900)
Change-Id: I487d6b7480b196124a12dd801be5458e4542a627
Signed-off-by: Sangjin Lee <lsj119@samsung.com>
configure.ac
src/bin/headless/output/output_led.c
src/bin/headless/shell/shell.c
src/lib/pepper/compositor.c
src/lib/pepper/output.c
src/lib/pepper/view.c
src/samples/headless_client.c

index 537b4a3..e9b5065 100644 (file)
@@ -317,9 +317,9 @@ AC_SUBST(SAMPLES_LIBS)
 # headless server
 HEADLESS_SERVER_REQUIRES="wayland-server capi-system-peripheral-io xdg-shell-unstable-v6-server tizen-extension-server"
 PKG_CHECK_MODULES(HEADLESS_SERVER, $[HEADLESS_SERVER_REQUIRES])
-HEADLESS_SERVER_CFLAGS="$PEPPER_DIR $PEPPER_KEYROUTER_DIR $PEPPER_EVDEV_DIR $HEADLESS_SERVER_CFLAGS"
+HEADLESS_SERVER_CFLAGS="$PEPPER_DIR $PEPPER_KEYROUTER_DIR $PEPPER_EVDEV_DIR $HEADLESS_SERVER_CFLAGS $TBM_CFLAGS"
 HEADLESS_SERVER_CFLAGS="$PEPPER_XKB_DIR $HEADLESS_SERVER_CFLAGS"
-HEADLESS_SERVER_LIBS="$PEPPER_LIB $PEPPER_LIBS $PEPPER_EVDEV_LIB $PEPPER_EVDEV_LIBS $HEADLESS_SERVER_LIBS"
+HEADLESS_SERVER_LIBS="$PEPPER_LIB $PEPPER_LIBS $PEPPER_EVDEV_LIB $PEPPER_EVDEV_LIBS $HEADLESS_SERVER_LIBS $TBM_LIBS"
 HEADLESS_SERVER_LIBS="$PEPPER_KEYROUTER_LIB $PEPPER_KEYROUTER_LIBS $HEADLESS_SERVER_LIBS"
 HEADLESS_SERVER_LIBS="$PEPPER_XKB_LIB $PEPPER_XKB_LIBS $HEADLESS_SERVER_LIBS"
 
index fec962f..aebad29 100644 (file)
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <tbm_bufmgr.h>
+#include <wayland-tbm-server.h>
 #include <pepper-output-backend.h>
 #include "HL_UI_LED.h"
 
@@ -37,9 +39,16 @@ typedef struct {
 
        int num_led;
        HL_UI_LED *ui_led;
+
+       struct wayland_tbm_server *tbm_server;
+       struct wl_event_source *frame_done;
+
+       pepper_view_t *top_view;
 }led_output_t;
 
 static const int KEY_OUTPUT;
+static void led_output_add_frame_done(led_output_t *output);
+static void led_output_update(led_output_t *output);
 
 static void
 led_output_destroy(void *o)
@@ -50,34 +59,33 @@ led_output_destroy(void *o)
        if (output->ui_led)
                HL_UI_LED_Close(output->ui_led);
 
+       if (output->tbm_server)
+               wayland_tbm_server_deinit(output->tbm_server);
+
        free(output);
 }
 
 static int32_t
 led_output_get_subpixel_order(void *o)
 {
-       PEPPER_TRACE("[OUTPUT]\n");
        return 0;
 }
 
 static const char *
 led_output_get_maker_name(void *o)
 {
-       PEPPER_TRACE("[OUTPUT]\n");
        return "PePPer LED";
 }
 
 static const char *
 led_output_get_model_name(void *o)
 {
-       PEPPER_TRACE("[OUTPUT]\n");
        return "PePPer LED";
 }
 
 static int
 led_output_get_mode_count(void *o)
 {
-       PEPPER_TRACE("[OUTPUT]\n");
        return 1;
 }
 
@@ -108,14 +116,22 @@ led_output_assign_planes(void *o, const pepper_list_t *view_list)
 {
        led_output_t *output = (led_output_t *)o;
        pepper_list_t *l;
-       pepper_view_t *view;
+       pepper_view_t *view, *top_view = NULL;
 
        PEPPER_TRACE("[OUTPUT] Assign plane\n");
        pepper_list_for_each_list(l, view_list) {
                view = (pepper_view_t*)l->item;
-               pepper_view_assign_plane(view, output->output, output->plane);
-               PEPPER_TRACE("\t view(%p) assign to output:%p plane:%p\n", view, output->output, output->plane);
+
+               if (pepper_view_is_mapped(view) && pepper_view_is_visible(view)) {
+                       top_view = view;
+                       break;
+               }
        }
+
+       if (output->top_view != top_view)
+               PEPPER_TRACE("\tTop-View is changed(%p -> %p)\n", output->top_view, top_view);
+
+       output->top_view = top_view;
 }
 
 static void
@@ -133,20 +149,18 @@ static void
 led_output_repaint(void *o, const pepper_list_t *plane_list)
 {
        pepper_list_t *l;
-       pepper_list_t *rl;
        pepper_plane_t *plane;
-       pepper_render_item_t *ritem;
+       led_output_t *output = (led_output_t *)o;
 
        PEPPER_TRACE("[OUTPUT] Repaint\n");
+
        pepper_list_for_each_list(l, plane_list) {
                plane = (pepper_plane_t *)l->item;
-               PEPPER_TRACE("\t plane:%p\n", plane);
-
-               pepper_list_for_each_list(rl, pepper_plane_get_render_list(plane)) {
-                       ritem = (pepper_render_item_t *)rl->item;
-                       PEPPER_TRACE("\t\t render item: view:%p\n", ritem->view);
-               }
+               pepper_plane_clear_damage_region(plane);
        }
+
+       led_output_update(output);
+       led_output_add_frame_done(output);
 }
 
 static void
@@ -154,14 +168,14 @@ led_output_attach_surface(void *o, pepper_surface_t *surface, int *w, int *h)
 {
        *w = 10;
        *h = 10;
-       PEPPER_TRACE("[OUTPUT] surface:%p\n", surface);
+       PEPPER_TRACE("[OUTPUT] attach surface:%p\n", surface);
 }
 
 static void
 led_output_flush_surface_damage(void *o, pepper_surface_t *surface, pepper_bool_t *keep_buffer)
 {
-       *keep_buffer = PEPPER_FALSE;
-       PEPPER_TRACE("[OUTPUT] surface:%p\n", surface);
+       *keep_buffer = PEPPER_TRUE;
+       PEPPER_TRACE("[OUTPUT] flush_surface_damage surface:%p\n", surface);
 }
 
 struct pepper_output_backend led_output_backend = {
@@ -182,6 +196,97 @@ struct pepper_output_backend led_output_backend = {
        led_output_flush_surface_damage,
 };
 
+static void
+led_output_update_led(led_output_t *output, unsigned char *data)
+{
+}
+
+static void
+led_output_update(led_output_t *output)
+{
+       pepper_buffer_t *buf;
+       pepper_surface_t *surface;
+       struct wl_resource *buf_res;
+       tbm_surface_h tbm_surface;
+       tbm_surface_info_s info;
+       int ret;
+
+       if (!output->top_view) {
+               if (!output->ui_led)
+                       PEPPER_TRACE("[UPDATE LED] Empty Display\n");
+               else
+                       led_output_update_led(output, NULL);
+
+               return;
+       }
+
+       surface = pepper_view_get_surface(output->top_view);
+       PEPPER_CHECK(surface, return, "fail to get a surafce from a view(%p)\n", output->top_view);
+
+       buf = pepper_surface_get_buffer(surface);
+       PEPPER_CHECK(buf, return, "fail to get a pepper_buffer from a surface(%p)\n", surface);
+
+       buf_res = pepper_buffer_get_resource(buf);
+       tbm_surface = wayland_tbm_server_get_surface(NULL, buf_res);
+       PEPPER_CHECK(tbm_surface, return, "fail to get a tbm_surface from a pepper_buffer(%p)\n", buf);
+
+       ret = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
+       PEPPER_CHECK(ret == TBM_SURFACE_ERROR_NONE, return, "fail to map the tbm_surface\n");
+
+       if (!output->ui_led)
+               PEPPER_TRACE("[UPDATE LED] %s\n", (char*)info.planes[0].ptr);
+       else
+               led_output_update_led(output, info.planes[0].ptr);
+
+       tbm_surface_unmap(tbm_surface);
+}
+
+static void
+led_output_cb_frame_done(void *data)
+{
+       led_output_t *output = (led_output_t *)data;
+
+       PEPPER_TRACE("[OUTPUT] frame_done\n");
+
+       pepper_output_finish_frame(output->output, NULL);
+       output->frame_done = NULL;
+}
+
+static void
+led_output_add_frame_done(led_output_t *output)
+{
+       struct wl_event_loop *loop;
+
+       PEPPER_TRACE("[OUTPUT] Add idle for frame(output:%p, frame:%p\n", output, output->frame_done);
+
+       if (!output || output->frame_done)
+               return;
+
+       loop = wl_display_get_event_loop(pepper_compositor_get_display(output->compositor));
+       PEPPER_CHECK(loop, return, "[OUTPUT] fail to get event loop\n");
+
+       output->frame_done = wl_event_loop_add_idle(loop, led_output_cb_frame_done, output);
+       PEPPER_CHECK(output->frame_done, return, "fail to add idle\n");
+}
+
+static void
+pepper_output_bind_display(led_output_t *output)
+{
+       tbm_bufmgr bufmgr = NULL;
+
+       PEPPER_CHECK(getenv("TBM_DISPLAY_SERVER"), return, "[TBM] run the subcompoitor mode\n");
+
+       bufmgr = wayland_tbm_server_get_bufmgr(output->tbm_server);
+       PEPPER_CHECK(bufmgr, return, "fail to get tbm_bufmgr\n");
+
+       if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)pepper_compositor_get_display(output->compositor)))
+       {
+               PEPPER_CHECK(0, return, "fail to tbm_bufmgr_bind_native_display\n");
+       }
+
+       return;
+}
+
 pepper_bool_t
 pepper_output_led_init(pepper_compositor_t *compositor)
 {
@@ -194,12 +299,17 @@ pepper_output_led_init(pepper_compositor_t *compositor)
                goto error;
        }
 
+       output->compositor = compositor;
+       output->tbm_server = wayland_tbm_server_init(pepper_compositor_get_display(compositor), NULL, -1, 0);
+       PEPPER_CHECK(output->tbm_server, goto error, "failed to wayland_tbm_server_init.\n");
+
+       pepper_output_bind_display(output);
+
        output->num_led = NUM_LED;
        output->ui_led = HL_UI_LED_Init(output->num_led);
        if (!output->ui_led)
                PEPPER_ERROR("HL_UI_LED_Init() failed.\n");
 
-       output->compositor = compositor;
        output->output = pepper_compositor_add_output(compositor,
                        &led_output_backend, "led_output",
                        output,  WL_OUTPUT_TRANSFORM_NORMAL, 1);
@@ -219,6 +329,9 @@ error:
        if (output->ui_led)
                HL_UI_LED_Close(output->ui_led);
 
+       if (output->tbm_server)
+               wayland_tbm_server_deinit(output->tbm_server);
+
        if (output->output)
                pepper_output_destroy(output->output);
 
index 8927c91..3962327 100644 (file)
@@ -923,6 +923,9 @@ static const struct tizen_policy_interface tizen_policy_iface =
 static void
 tizen_policy_cb_unbind(struct wl_resource *resource)
 {
+       headless_shell_t *shell = (headless_shell_t *)wl_resource_get_user_data(resource);
+
+       shell->tizen_policy = NULL;
 }
 
 static void
@@ -965,7 +968,7 @@ tizen_policy_init(headless_shell_t *shell)
 void
 tizen_policy_deinit(headless_shell_t *shell)
 {
-       if (shell->zxdg_shell)
+       if (shell->tizen_policy)
                wl_global_destroy(shell->tizen_policy);
 }
 
@@ -1087,7 +1090,7 @@ headless_shell_add_idle(headless_shell_t *shell)
 {
        struct wl_event_loop *loop;
 
-       if (shell->cb_idle)
+       if (!shell || shell->cb_idle)
                return;
 
        loop = wl_display_get_event_loop(pepper_compositor_get_display(shell->compositor));
index ad4da74..9d92826 100644 (file)
@@ -185,7 +185,7 @@ pepper_compositor_schedule_repaint(pepper_compositor_t *compositor)
        pepper_output_t *output;
 
        pepper_list_for_each(output, &compositor->output_list, link)
-       pepper_output_schedule_repaint(output);
+               pepper_output_schedule_repaint(output);
 }
 
 /**
index 5630e97..9d68a4c 100644 (file)
@@ -125,7 +125,7 @@ output_update_planes(pepper_output_t *output)
        pepper_region_init(&clip);
 
        pepper_list_for_each_reverse(plane, &output->plane_list, link)
-       pepper_plane_update(plane, &output->view_list, &clip);
+               pepper_plane_update(plane, &output->view_list, &clip);
 
        pepper_region_fini(&clip);
 }
index ded296f..bcf6105 100644 (file)
@@ -35,8 +35,10 @@ pepper_view_mark_dirty(pepper_view_t *view, uint32_t flag)
        pepper_view_t  *child;
        int             i;
 
-       if (view->dirty & flag)
+       if (view->dirty & flag) {
+               PEPPER_TRACE("pepper_view_mark_dirty view:%p, dirty:%x, flag:%x\n", view, view->dirty, flag);
                return;
+       }
 
        view->dirty |= flag;
 
@@ -162,14 +164,18 @@ pepper_view_update(pepper_view_t *view)
        if (view->active == active)
                view->dirty &= ~PEPPER_VIEW_ACTIVE_DIRTY;
 
-       if (!view->dirty)
+       if (!view->dirty) {
+               PEPPER_TRACE("pepper_view_update view:%p not dirty\n", view);
                return;
+       }
 
        view->active = active;
 
        /* Damage for the view unmap will be handled by assigning NULL plane. */
-       if (!view->active)
+       if (!view->active) {
+               PEPPER_TRACE("pepper_view_update view:%p not active\n", view);
                return;
+       }
 
        /* We treat the modification as unmapping and remapping the view. So,
         * damage for the unmap and damage for the remap.
index 3ce783e..70f5d72 100644 (file)
@@ -3,6 +3,8 @@
 #include <unistd.h>
 #include <Ecore_Wl2.h>
 #include <Ecore_Input.h>
+#include <wayland-tbm-client.h>
+#include <tbm_surface_internal.h>
 
 #define DISPLAY_NAME "headless-0"
 
@@ -33,10 +35,81 @@ struct app_data
 {
        Ecore_Wl2_Display *ewd;
        Ecore_Wl2_Window *win;
+
+       struct wayland_tbm_client *wl_tbm_client;
+       tbm_surface_queue_h tbm_queue;
+       int last_serial;
 };
 
 static Eina_Array *_ecore_event_hdls;
 
+static int KEY_WL_BUFFER = 0;
+static int KEY_CLIENT = 0;
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+       tbm_surface_h surface = (tbm_surface_h)data;
+       app_data_t *client;
+
+       tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_CLIENT, (void **)&client);
+       tbm_surface_queue_release(client->tbm_queue, surface);
+
+       //TRACE("[UPDATE] release wl_buffer:%p, surface:%p\n", buffer, surface);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+    buffer_release
+};
+
+static void
+_update_window(app_data_t *client)
+{
+       struct wl_buffer *wl_buffer = NULL;
+       tbm_surface_h surface;
+       tbm_surface_error_e ret;
+
+       ERROR_CHECK(tbm_surface_queue_can_dequeue(client->tbm_queue, 0), return, "[UPDATE] Cannot dequeue\n");
+
+       ret = tbm_surface_queue_dequeue(client->tbm_queue, &surface);
+       ERROR_CHECK(ret == TBM_SURFACE_ERROR_NONE, return, "[UPDATE] dequeue err:%d\n", ret);
+
+       /*TODO : Update something*/
+       {
+               tbm_surface_info_s info;
+
+               tbm_surface_map(surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &info);
+               snprintf((char *)info.planes[0].ptr,info.planes[0].size, "%s : %d", "DATA print", client->last_serial);
+               TRACE("[APP] %s\n", info.planes[0].ptr);
+               tbm_surface_unmap(surface);
+               client->last_serial++;
+       }
+
+       ret = tbm_surface_queue_enqueue(client->tbm_queue, surface);
+       ERROR_CHECK(ret == TBM_SURFACE_ERROR_NONE, return, "[UPDATE] enqueue err:%d\n", ret);
+
+       ret = tbm_surface_queue_acquire(client->tbm_queue, &surface);
+       ERROR_CHECK(ret == TBM_SURFACE_ERROR_NONE, return, "[UPDATE] acquire err:%d\n", ret);
+
+       if (!tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_WL_BUFFER, (void **)&wl_buffer)) {
+               wl_buffer = wayland_tbm_client_create_buffer(client->wl_tbm_client, surface);
+               ERROR_CHECK(wl_buffer, return, "[UPDATE] failed to create wl_buffer tbm_surface:%p\n", surface);
+
+               wl_buffer_add_listener(wl_buffer, &buffer_listener, surface);
+
+               tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_WL_BUFFER, NULL);
+               tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_WL_BUFFER, wl_buffer);
+               tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_CLIENT, NULL);
+               tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_CLIENT, client);
+       }
+       ERROR_CHECK(wl_buffer, return, "[UPDATE] dequeue err:%d\n", ret);
+
+       ecore_wl2_window_buffer_attach(client->win, wl_buffer, 0, 0, 0);
+       ecore_wl2_window_damage(client->win, NULL, 0);
+       ecore_wl2_window_commit(client->win, EINA_TRUE);
+       //TRACE("[UPDATE] commit wl_buffer:%p, surface:%p\n", wl_buffer, surface);
+}
+
 static uint32_t _getpid()
 {
        static pid_t pid = 0;
@@ -194,11 +267,7 @@ _cb_key_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
        app_data_t *client =  (app_data_t *)data;
        Ecore_Event_Key *ev = event;
 
-       TRACE("\n");
-
-       /* TODO */
-       (void) client;
-       (void) ev;
+       TRACE("KEY: name:%s, sym:%s, code:%d\n", ev->keyname, ev->key, ev->keycode);
 
        do_action(client, ev->keyname);
 
@@ -276,23 +345,44 @@ int main(int argc, char **argv)
        client->ewd = ecore_wl2_display_connect(DISPLAY_NAME);
        ERROR_CHECK(client->ewd, goto shutdown, "Failed to connect to wayland display %s", DISPLAY_NAME);
 
+       client->wl_tbm_client = wayland_tbm_client_init(ecore_wl2_display_get(client->ewd));
+       ERROR_CHECK(client->wl_tbm_client, goto shutdown, "Failed to init wayland_tbm_client");
+
        _event_handlers_init(client);
 
+       /*Create Sample Window*/
        x = y = 0;
        w = h = 1;
        client->win = ecore_wl2_window_new(client->ewd, NULL, x, y, w, h);
+       ecore_wl2_window_alpha_set(client->win, EINA_FALSE);
        ecore_wl2_window_show(client->win);
        ecore_wl2_window_activate(client->win);
        ecore_wl2_window_commit(client->win, EINA_TRUE);
 
+       client->tbm_queue = wayland_tbm_client_create_surface_queue(client->wl_tbm_client,
+                                                                                               ecore_wl2_window_surface_get(client->win),
+                                                                                               2,
+                                                                                               100, 100,
+                                                                                               TBM_FORMAT_ABGR8888);
+       ERROR_CHECK(client->tbm_queue, goto shutdown, "Failed to create tbm_surface_queue");
+
        usage();
 
-       /* TODO */
+       /*Start Loop*/
        ecore_main_loop_begin();
 
-       return EXIT_SUCCESS;
-
 shutdown:
-       return EXIT_FAILURE;
+       if (client) {
+               if (client->tbm_queue)
+                       tbm_surface_queue_destroy(client->tbm_queue);
+
+               if (client->wl_tbm_client)
+                       wayland_tbm_client_deinit(client->wl_tbm_client);
+
+               ecore_wl2_shutdown();
+               free(client);
+       }
+
+       return EXIT_SUCCESS;
 }