# 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"
#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"
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)
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;
}
{
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
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
{
*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 = {
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)
{
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);
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);
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
void
tizen_policy_deinit(headless_shell_t *shell)
{
- if (shell->zxdg_shell)
+ if (shell->tizen_policy)
wl_global_destroy(shell->tizen_policy);
}
{
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));
pepper_output_t *output;
pepper_list_for_each(output, &compositor->output_list, link)
- pepper_output_schedule_repaint(output);
+ pepper_output_schedule_repaint(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);
}
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;
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.
#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"
{
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;
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);
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;
}