From: Wataru Mizuno Date: Wed, 4 Jul 2018 06:25:39 +0000 (+0900) Subject: trasnmitter: initial commit for waltham-transmitter X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=5410b7686d850e247ff9881f890cd5a86035b644;p=AGL%2Fmeta-agl.git trasnmitter: initial commit for waltham-transmitter The waltham-transmitter is the plugin of weston to enable client apps to share its surface between multiple domains. Change-Id: I7e607ed183f147fc0078bef54639207cfca80c6e Signed-off-by: Wataru Mizuno --- diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch new file mode 100644 index 000000000..a27788d71 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch @@ -0,0 +1,3932 @@ +From 2bcc81912b92d6ba7a6d24e972e0bcce2e746cab Mon Sep 17 00:00:00 2001 +From: Wataru Mizuno +Date: Wed, 4 Jul 2018 09:09:33 +0900 +Subject: [PATCH] transmitter: initial commit for waltham-transmitter + +The waltham-transmitter is the plugin of weston to enable client +applications to share its surface between multiple domains. + +Signed-off-by: Wataru Mizuno +--- + CMakeLists.txt | 3 + + waltham-transmitter/CMakeLists.txt | 4 + + waltham-transmitter/COPYING | 30 + + .../transmitter-plugin/CMakeLists.txt | 62 + + waltham-transmitter/transmitter-plugin/README | 97 ++ + waltham-transmitter/transmitter-plugin/input.c | 1317 ++++++++++++++++++++ + waltham-transmitter/transmitter-plugin/output.c | 352 ++++++ + waltham-transmitter/transmitter-plugin/plugin.c | 940 ++++++++++++++ + waltham-transmitter/transmitter-plugin/plugin.h | 330 +++++ + .../transmitter-plugin/transmitter_api.h | 278 +++++ + .../transmitter-plugin/weston.ini.transmitter | 21 + + .../waltham-renderer/CMakeLists.txt | 59 + + .../waltham-renderer/waltham-renderer.c | 270 ++++ + .../waltham-renderer/waltham-renderer.h | 41 + + 14 files changed, 3804 insertions(+) + create mode 100644 CMakeLists.txt + create mode 100644 waltham-transmitter/CMakeLists.txt + create mode 100644 waltham-transmitter/COPYING + create mode 100644 waltham-transmitter/transmitter-plugin/CMakeLists.txt + create mode 100644 waltham-transmitter/transmitter-plugin/README + create mode 100644 waltham-transmitter/transmitter-plugin/input.c + create mode 100644 waltham-transmitter/transmitter-plugin/output.c + create mode 100644 waltham-transmitter/transmitter-plugin/plugin.c + create mode 100644 waltham-transmitter/transmitter-plugin/plugin.h + create mode 100644 waltham-transmitter/transmitter-plugin/transmitter_api.h + create mode 100644 waltham-transmitter/transmitter-plugin/weston.ini.transmitter + create mode 100644 waltham-transmitter/waltham-renderer/CMakeLists.txt + create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.c + create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +new file mode 100644 +index 0000000..00fd14e +--- /dev/null ++++ b/CMakeLists.txt +@@ -0,0 +1,3 @@ ++project (weston-ivi-plugins) ++ ++add_subdirectory(waltham-transmitter) +diff --git a/waltham-transmitter/CMakeLists.txt b/waltham-transmitter/CMakeLists.txt +new file mode 100644 +index 0000000..b4d1243 +--- /dev/null ++++ b/waltham-transmitter/CMakeLists.txt +@@ -0,0 +1,4 @@ ++project (transmitter) ++ ++add_subdirectory(transmitter-plugin) ++add_subdirectory(waltham-renderer) +diff --git a/waltham-transmitter/COPYING b/waltham-transmitter/COPYING +new file mode 100644 +index 0000000..faefd8f +--- /dev/null ++++ b/waltham-transmitter/COPYING +@@ -0,0 +1,30 @@ ++Copyright © 2008-2012 Kristian Høgsberg ++Copyright © 2010-2012 Intel Corporation ++Copyright © 2010-2011 Benjamin Franzke ++Copyright © 2011-2012 Collabora, Ltd. ++Copyright © 2010 Red Hat ++ ++Permission is hereby granted, free of charge, to any person obtaining a ++copy of this software and associated documentation files (the "Software"), ++to deal in the Software without restriction, including without limitation ++the rights to use, copy, modify, merge, publish, distribute, sublicense, ++and/or sell copies of the Software, and to permit persons to whom the ++Software is furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice (including the next ++paragraph) shall be included in all copies or substantial portions of the ++Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++DEALINGS IN THE SOFTWARE. ++ ++--- ++ ++The above is the version of the MIT "Expat" License used by X.org: ++ ++ http://cgit.freedesktop.org/xorg/xserver/tree/COPYING +diff --git a/waltham-transmitter/transmitter-plugin/CMakeLists.txt b/waltham-transmitter/transmitter-plugin/CMakeLists.txt +new file mode 100644 +index 0000000..a900d3b +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/CMakeLists.txt +@@ -0,0 +1,62 @@ ++project (transmitter) ++ ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) ++pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) ++pkg_check_modules(PIXMAN pixman-1 REQUIRED) ++pkg_check_modules(WALTHAM waltham REQUIRED) ++ ++include_directories( ++ include ++ ${CMAKE_SOURCE_DIR}/waltham-transmitter/waltham-renderer ++ ${CMAKE_CURRENT_BINARY_DIR} ++ ${WAYLAND_CLIENT_INCLUDE_DIRS} ++ ${WAYLAND_SERVER_INCLUDE_DIRS} ++ ${WESTON_INCLUDE_DIRS} ++ ${PIXMAN_INCLUDE_DIRS} ++ ${WALTHAM_INCLUDE_DIRS} ++) ++ ++link_directories( ++ ${WAYLAND_SERVER_LIBRARY_DIRS} ++ ${WESTON_LIBRARY_DIRS} ++ ${PIXMAN_LIBRARY_DIRS} ++ ${WALTHAM_LIBRARY_DIRS} ++) ++ ++add_library(${PROJECT_NAME} MODULE ++ plugin.c ++ output.c ++ input.c ++ plugin.h ++ transmitter_api.h ++) ++ ++set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") ++ ++set(LIBS ++ m ++ ${WAYLAND_SERVER_LIBRARIES} ++ ${WESTON_LIBRARIES} ++ ${PIXMAN_LIBRARIES} ++ ${WALTHAM_LIBRARIES} ++) ++ ++SET(SRC_FILES ++ plugin.c ++ output.c ++ input.c ++ plugin.h ++ transmitter_api.h ++) ++ ++ ++ ++add_dependencies(${PROJECT_NAME} ${LIBS}) ++ ++target_link_libraries(${PROJECT_NAME} ${LIBS}) ++ ++install ( ++ TARGETS ${PROJECT_NAME} ++ LIBRARY DESTINATION lib64/weston ++) +diff --git a/waltham-transmitter/transmitter-plugin/README b/waltham-transmitter/transmitter-plugin/README +new file mode 100644 +index 0000000..345142d +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/README +@@ -0,0 +1,97 @@ ++Transmitter plugin ++ ++The current implementation of Transmitter is a stub which interfaces to ++other Weston parts appropriately, but all networking is just a mockup. ++ ++Sections in this file describe: ++- How to build ++- How to write weston.ini ++- How to test ++ ++How to build ++============ ++Configure Weston with --enable-surface-remoting to build the Transmitter ++plugin. ++ ++How to write weston.ini ++======================= ++To load transmitter plugin to weston, add 'transmitter.so' to the 'modules' ++key under '[core]', and make sure the 'shell' is 'ivi-shell.so'. ++ ++The destination of remoting is configured in weston.ini. ++Add output name, server address, port number, output's width and height key ++under '[remote-output]'. ++You can speficy multiple [remote-output]. ++ ++In details, see 'weston.ini.transmitter'. ++ ++How to test ++=========== ++You can use server side test application in waltham-server directory. ++ ++If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can ++see the log like this: ++ ++ [13:24:08.345] Loading module '/usr/lib64/weston/transmitter.so' ++ [13:24:08.345] Registered plugin API 'transmitter_v1' of size 88 ++ [13:24:08.345] Registered plugin API 'transmitter_ivi_v1' of size 16 ++ [13:24:08.345] Transmitter initialized. ++ [13:24:08.345] Loading module '/usr/lib64/libweston-2/waltham-renderer.so' ++ [13:24:08.352] gst-setting are :--> ++ [13:24:08.352] ip = 192.168.2.52 ++ [13:24:08.352] port = 34400 ++ [13:24:08.352] bitrate = 3000000 ++ [13:24:08.352] crop = 384 x 368 ++ [13:24:08.352] width = 1920 ++ [13:24:08.352] width = 1080 ++ [13:24:08.531] open media device: platform:fe960000.vsp (fe960000.vsp) ++ [13:24:08.532] input pad setup ('fe960000.vsp rpf.0 input':'/dev/video0') ++ [13:24:08.533] output pad setup (fe960000.vsp wpf.0 output:/dev/video5) ++ [13:24:08.533] vsp-device '/dev/media0' created ++ [13:24:08.533] gst_recorder_create (1920x1080) crop 384x368 at 0,0 ++ [13:24:08.533] gst_pipeline: starting: appsrc name=src ! omxh264enc target-bitrate=3000000 control-rate=2 no-copy=k ++ [13:24:08.582] goot 1 pools ++ [13:24:08.583] pool settings size 211968, min 5, max 5 ++ [13:24:08.583] gst_recorder_create done ++ [13:24:08.583] [gst recorder] transmitter-192.168.2.52:34400-1: recorder initialized ++ [13:24:08.583] Transmitter weston_seat 0x15424630 ++ [13:24:08.583] Transmitter created pointer=0x15625df0 for seat 0x15424630 ++ [13:24:08.583] Transmitter created keyboard=0x154247c0 for seat 0x15424630 ++ [13:24:08.583] Transmitter created touch=0x15625f10 for seat 0x15424630 ++ ++The connection is established, you can see following debug messages: ++ ++ debug: wth_connection_insert_new_object: new object id: 1 ++ debug: wth_connection_insert_new_object: new object id: 2 ++ 2018-01-09T13:24:22Z 00001000030000000100000002000000 wth_display_get_registry ++ debug: wth_connection_insert_new_object: new object id: 3 ++ 2018-01-09T13:24:22Z 00001000020000000100000003000000 wth_display_sync ++ debug: Message received on conn 0x15572730: (9) 40 bytes ++ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. ++ debug: wth_connection_insert_new_object: new object id: 4 ++ 2018-01-09T13:24:22Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthpd ++ debug: Message received on conn 0x15572730: (9) 48 bytes ++ debug: wthp_registry_send_global(2, 1, [variable type const char *], 1) (opcode 9) called. ++ debug: wth_connection_insert_new_object: new object id: 5 ++ 2018-01-09T13:24:22Z 000034000800000002000000010000000500000015000000777468705f6976695f6170706c69636174696f6e00010d ++ debug: Message received on conn 0x15572730: (9) 44 bytes ++ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. ++ debug: wth_connection_insert_new_object: new object id: 6 ++ 2018-01-09T13:24:22Z 000030000800000002000000010000000600000012000000777468705f626c6f625f666163746f72790001000000 d ++ debug: Message received on conn 0x15572730: (9) 36 bytes ++ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. ++ debug: wth_connection_insert_new_object: new object id: 7 ++ 2018-01-09T13:24:22Z 00002800080000000200000001000000070000000a000000777468705f736561740001000000 wthp_registry_bid ++ debug: Message received on conn 0x15572730: (11) 16 bytes ++ debug: wthp_callback_send_done(3, 0) (opcode 11) called. ++ ++Start remoting : ++- Start an IVI application. ++- Put surface on transmitter output ++ ++Weston log will indicate remoting has started: ++ ++[13:18:24.572] HMI transmitting surface 0x1c3dad0, ivi-id 0x9ff6 ++[13:18:24.572] Transmitter: update surface 0x1c3dad0 (0, 0), 0 cb ++[13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6) ++[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 +\ No newline at end of file +diff --git a/waltham-transmitter/transmitter-plugin/input.c b/waltham-transmitter/transmitter-plugin/input.c +new file mode 100644 +index 0000000..e00546b +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/input.c +@@ -0,0 +1,1317 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++/* for fake stuff */ ++#include ++ ++#include "compositor.h" ++ ++#include "plugin.h" ++#include "transmitter_api.h" ++ ++/** @file ++ * ++ * This is an implementation of a remote input. ++ * ++ * Request wl_data_device_manager.get_data_device would need to be blocked, ++ * except maybe it's not necessary, we just "forget" to forward data to/from ++ * the remote wl_seat. It might still work inside the local compositor. ++ * ++ * weston_compositor_set_default_pointer_grab() will break our pointer ++ * implementation, but no in-tree code is calling it. ++ */ ++ ++/* XXX: all functions and variables with a name, and things marked with a ++ * comment, containing the word "fake" are mockups that need to be ++ * removed from the final implementation. ++ */ ++ ++static void ++pointer_focus_grab_handler(struct weston_pointer_grab *grab) ++{ ++ /* No-op: ++ * ++ * Weston internal events do not change the focus. ++ */ ++} ++ ++static void ++pointer_motion_grab_handler(struct weston_pointer_grab *grab, ++ uint32_t time, ++ struct weston_pointer_motion_event *event) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++static void ++pointer_button_grab_handler(struct weston_pointer_grab *grab, ++ uint32_t time, ++ uint32_t button, ++ uint32_t state) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++static void ++pointer_axis_grab_handler(struct weston_pointer_grab *grab, ++ uint32_t time, ++ struct weston_pointer_axis_event *event) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++static void ++pointer_axis_source_grab_handler(struct weston_pointer_grab *grab, ++ uint32_t source) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++static void ++pointer_frame_grab_handler(struct weston_pointer_grab *grab) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++static void ++pointer_cancel_grab_handler(struct weston_pointer_grab *grab) ++{ ++ weston_log("Unexpected! %s(pointer=%p, ...)\n", ++ __func__, grab->pointer); ++} ++ ++/* These handlers would be called from the notify_*() functions in src/input.c. ++ * However, as we do not use the low level input notify_*() functions that ++ * backends drive, these are mostly uncalled, except the focus handler which ++ * weston core generates internally. ++ */ ++static const struct weston_pointer_grab_interface pointer_grab_impl = { ++ pointer_focus_grab_handler, ++ pointer_motion_grab_handler, ++ pointer_button_grab_handler, ++ pointer_axis_grab_handler, ++ pointer_axis_source_grab_handler, ++ pointer_frame_grab_handler, ++ pointer_cancel_grab_handler, ++}; ++ ++static void ++keyboard_grab_key(struct weston_keyboard_grab *grab, ++ uint32_t time, ++ uint32_t key, ++ uint32_t state) ++{ ++} ++ ++static void ++keyboard_grab_modifiers(struct weston_keyboard_grab *grab, ++ uint32_t serial, ++ uint32_t mods_depressed, ++ uint32_t mods_latched, ++ uint32_t mods_locked, ++ uint32_t group) ++{ ++} ++ ++static void ++keyboard_grab_cancel(struct weston_keyboard_grab *grab) ++{ ++} ++ ++static const struct weston_keyboard_grab_interface keyborad_grab_impl = { ++ keyboard_grab_key, ++ keyboard_grab_modifiers, ++ keyboard_grab_cancel ++}; ++ ++static void ++touch_grab_down_handler(struct weston_touch_grab *grab, ++ uint32_t time, ++ int touch_id, ++ wl_fixed_t x, ++ wl_fixed_t y) ++{ ++} ++ ++static void ++touch_grab_up_handler(struct weston_touch_grab *grab, ++ uint32_t time, ++ int touch_id) ++{ ++} ++ ++static void ++touch_grab_motion_handler(struct weston_touch_grab *grab, ++ uint32_t time, ++ int touch_id, ++ wl_fixed_t x, ++ wl_fixed_t y) ++{ ++} ++ ++static void ++touch_grab_frame_handler(struct weston_touch_grab *grab) ++{ ++} ++ ++static void ++touch_grab_cancel_handler(struct weston_touch_grab *grab) ++{ ++} ++ ++static const struct weston_touch_grab_interface touch_grab_impl = { ++ touch_grab_down_handler, ++ touch_grab_up_handler, ++ touch_grab_motion_handler, ++ touch_grab_frame_handler, ++ touch_grab_cancel_handler, ++}; ++ ++ ++/* The different ways to get pointer focus on a remoted surface: ++ * ++ * 1. Transmitter seat has pointer. The client has wl_pointer. Transmitter ++ * receives pointer.enter. (transmitter_seat_pointer_enter()) ++ * ++ * 2. Transmitter seat has pointer. Transmitter has received pointer.enter. ++ * The client calls wl_seat.get_pointer. => send enter only on the new ++ * wl_pointer. (seat_get_pointer_handler()) ++ * ++ * 3. Client has wl_pointer. Transmitter seat adds pointer capability. ++ * Transmitter receives pointer.enter. wl_pointer MUST NOT enter, ++ * specified by wl_seat.capabilities. ++ * ++ * By definition, Transmitter cannot receive pointer.enter without having ++ * pointer capability in the seat, so no other combinations are possible. ++ * ++ * The same applies to wl_keyboard and wl_touch. ++ */ ++ ++/* Implementor notes: ++ * ++ * The handling of all of wl_pointer, wl_keyboard and wl_touch should be ++ * similar. To make it work, we need to add a signal to each of the ++ * wl_seat.get_pointer, wl_seat.get_keyboard, and wl_seat.get_touch request ++ * handlers in Weston core. Otherwise we cannot implement the case 2 of gaining ++ * input device focus. ++ * ++ * However, weston_keyboard::focus is a weston_surface, not a weston_view, so ++ * we may be able to leverage more of the core implementation and maybe do ++ * without the wl_seat.get_keyboard signal. Weston_touch uses a weston_view, so ++ * that is similar to weston_pointer. ++ * ++ * It might be useful to convert weston_keyboard and weston_touch to use a ++ * similar thing as weston_pointer_client, in case it makes things more ++ * consistent. It might also fix issues when a client has multiple copies of a ++ * wl_keyboard or a wl_touch, but that is getting off-topic. ++ * ++ * This file shows which part of the Weston input path we skip and where we ++ * hook in. We skip everything starting from the notify_*() API used by ++ * backends, and stub out the grab handlers. Instead of actual grab handlers, ++ * we have our own network protocol events handlers. They do much of the same ++ * as normal grab handlers would do, except focus is pre-given, and we do not ++ * have weston_view for the focus surfaces, so we need to bypass core code ++ * dealing with those. ++ * ++ * Our remote seat implementation will leave many struct members unused and ++ * replicate some from weston_pointer, weston_keyboard, and weston_touch. ++ * Weston core must be kept out from the focus handling business, because we ++ * will send enter/leave events ourselves, and focus assignments are given ++ * to us from the remote, they cannot be changed at will by the local Weston. ++ */ ++ ++/** Callback from the protocol request handler for wl_seat.get_pointer ++ * ++ * The Weston core handler never sees focus set on the weston_pointer, ++ * so it won't send wl_pointer.enter nor set focus_client. It does call ++ * weston_pointer_ensure_pointer_client() though. ++ */ ++static void ++seat_get_pointer_handler(struct wl_listener *listener, void *data) ++{ ++ struct wl_resource *new_pointer = data; ++ struct weston_transmitter_seat *seat; ++ struct wl_resource *surface; ++ struct weston_pointer_client *pointer_client; ++ struct wl_client *client; ++ struct weston_pointer *pointer; ++ ++ seat = wl_container_of(listener, seat, get_pointer_listener); ++ if (!seat->pointer_focus) ++ return; ++ ++ client = wl_resource_get_client(new_pointer); ++ surface = seat->pointer_focus->surface->resource; ++ ++ if (wl_resource_get_client(surface) != client) ++ return; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); /* guaranteed by having pointer_focus */ ++ pointer_client = weston_pointer_get_pointer_client(pointer, client); ++ ++ if (!pointer->focus_client) ++ pointer->focus_client = pointer_client; ++ else ++ assert(pointer->focus_client == pointer_client); ++ ++ wl_pointer_send_enter(new_pointer, pointer->focus_serial, surface, ++ seat->pointer_surface_x, seat->pointer_surface_y); ++ ++ if (wl_resource_get_version(new_pointer) >= ++ WL_POINTER_FRAME_SINCE_VERSION) ++ wl_pointer_send_frame(new_pointer); ++} ++ ++static void ++transmitter_seat_create_pointer(struct weston_transmitter_seat *seat) ++{ ++ struct weston_pointer *pointer; ++ ++ seat->pointer_phase = 0.0; ++ seat->pointer_surface_x = wl_fixed_from_int(-1000000); ++ seat->pointer_surface_y = wl_fixed_from_int(-1000000); ++ seat->pointer_focus = NULL; ++ wl_list_init(&seat->pointer_focus_destroy_listener.link); ++ ++ weston_seat_init_pointer(seat->base); ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ ++ /* not exported: ++ * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */ ++ pointer->default_grab.interface = &pointer_grab_impl; ++ ++ /* Changes to local outputs are irrelevant. */ ++ wl_list_remove(&pointer->output_destroy_listener.link); ++ wl_list_init(&pointer->output_destroy_listener.link); ++ ++ weston_log("Transmitter created pointer=%p for seat %p\n", ++ pointer, seat->base); ++} ++ ++static void ++seat_pointer_focus_destroy_handler(struct wl_listener *listener, void *data) ++{ ++ struct weston_transmitter_surface *txs = data; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(listener, seat, pointer_focus_destroy_listener); ++ assert(seat->pointer_focus == txs); ++ ++ seat->pointer_focus = NULL; ++} ++ ++void ++transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs, ++ wl_fixed_t surface_x, ++ wl_fixed_t surface_y) ++{ ++ struct wl_client *client; ++ struct weston_pointer *pointer; ++ struct wl_list *focus_resource_list; ++ struct wl_resource *resource; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); ++ ++ assert(txs->surface); ++ client = wl_resource_get_client(txs->surface->resource); ++ ++ seat->pointer_focus = txs; ++ seat->pointer_focus_destroy_listener.notify = ++ seat_pointer_focus_destroy_handler; ++ wl_signal_add(&txs->destroy_signal, ++ &seat->pointer_focus_destroy_listener); ++ ++ /* If pointer-focus gets destroyed, txs will get destroyed, the ++ * remote surface object is destroyed, and the remote will send a ++ * leave and a frame. ++ */ ++ ++ seat->pointer_surface_x = surface_x; ++ seat->pointer_surface_y = surface_y; ++ ++ pointer->focus_serial = serial; ++ ++ /* pointer->focus is not used, because it is a weston_view, while ++ * remoted surfaces have no views. ++ * ++ * pointer->x,y are not used because they are in global coordinates. ++ * Remoted surfaces are not in the global space at all, so there are ++ * no such coordinates. ++ */ ++ ++ if (!pointer->focus_client) ++ return; ++ ++ focus_resource_list = &pointer->focus_client->pointer_resources; ++ wl_resource_for_each(resource, focus_resource_list) { ++ wl_pointer_send_enter(resource, ++ serial, ++ txs->surface->resource, ++ surface_x, surface_y); ++ } ++} ++ ++void ++transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs) ++{ ++ struct weston_pointer *pointer; ++ struct wl_list *focus_resource_list; ++ struct wl_resource *surface_resource; ++ struct wl_resource *resource; ++ ++ if (txs != seat->pointer_focus) { ++ weston_log("Transmitter Warning: pointer leave for %p, expected %p\n", ++ txs, seat->pointer_focus); ++ } ++ ++ seat->pointer_focus = NULL; ++ wl_list_remove(&seat->pointer_focus_destroy_listener.link); ++ wl_list_init(&seat->pointer_focus_destroy_listener.link); ++ ++ if (!txs) ++ return; ++ assert(txs->surface); ++ surface_resource = txs->surface->resource; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); ++ if (!pointer->focus_client) ++ return; ++ ++ focus_resource_list = &pointer->focus_client->pointer_resources; ++ wl_resource_for_each(resource, focus_resource_list) ++ wl_pointer_send_leave(resource, serial, surface_resource); ++ ++ /* Do not reset pointer->focus_client, because we need to be able ++ * to send a following 'frame' event in ++ * transmitter_seat_pointer_frame(). ++ */ ++} ++ ++void ++transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ wl_fixed_t surface_x, ++ wl_fixed_t surface_y) ++{ ++ struct weston_pointer *pointer; ++ struct wl_list *focus_resource_list; ++ struct wl_resource *resource; ++ struct weston_transmitter_surface *txs; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); ++ ++ seat->pointer_surface_x = surface_x; ++ seat->pointer_surface_y = surface_y; ++ ++ if (!pointer->focus_client) ++ return; ++ ++ txs = seat->pointer_focus; ++ if (txs) ++ assert(wl_resource_get_client(txs->surface->resource) == ++ pointer->focus_client->client); ++ ++ focus_resource_list = &pointer->focus_client->pointer_resources; ++ wl_resource_for_each(resource, focus_resource_list) { ++ wl_pointer_send_motion(resource, time, ++ surface_x, surface_y); ++ } ++} ++ ++void ++transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ uint32_t time, ++ uint32_t button, ++ uint32_t state) ++{ ++ struct weston_pointer *pointer; ++ struct wl_list *focus_resource_list; ++ struct wl_resource *resource; ++ struct weston_transmitter_surface *txs; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); ++ ++ if (!pointer->focus_client) ++ return; ++ ++ txs = seat->pointer_focus; ++ if (txs) ++ assert(wl_resource_get_client(txs->surface->resource) == ++ pointer->focus_client->client); ++ ++ focus_resource_list = &pointer->focus_client->pointer_resources; ++ wl_resource_for_each(resource, focus_resource_list) { ++ wl_pointer_send_button(resource, serial, time, ++ button, state); ++ } ++} ++ ++void ++transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ uint32_t axis, ++ wl_fixed_t value) ++{ ++ struct weston_pointer *pointer; ++ struct wl_list *focus_resource_list; ++ struct wl_resource *resource; ++ struct weston_transmitter_surface *txs; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ assert(pointer); ++ ++ if (!pointer->focus_client) ++ return; ++ ++ txs = seat->pointer_focus; ++ if (txs) ++ assert(wl_resource_get_client(txs->surface->resource) == ++ pointer->focus_client->client); ++ ++ focus_resource_list = &pointer->focus_client->pointer_resources; ++ wl_resource_for_each(resource, focus_resource_list) { ++ wl_pointer_send_axis(resource, time, ++ axis, value); ++ } ++} ++ ++void ++transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat) ++{ ++ struct weston_pointer *pointer; ++ ++ pointer = weston_seat_get_pointer(seat->base); ++ if (pointer) ++ weston_pointer_send_frame(pointer); ++} ++ ++void ++transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, ++ uint32_t axis_source) ++{ ++ /* ToDo : implement axis event handling */ ++} ++ ++void ++transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ uint32_t axis) ++{ ++ /* ToDo : implement axis event handling */ ++} ++ ++void ++transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, ++ uint32_t axis, ++ int32_t discrete) ++{ ++ /* ToDo : implement axis event handling */ ++} ++ ++static void ++transmitter_seat_create_keyboard(struct weston_transmitter_seat *seat) ++{ ++ struct weston_keyboard *keyboard; ++ ++ seat->keyboard_focus = NULL; ++ weston_seat_init_keyboard(seat->base, NULL); ++ ++ keyboard = weston_seat_get_keyboard(seat->base); ++ ++ keyboard->default_grab.interface = &keyborad_grab_impl; ++ ++ weston_log("Transmitter created keyboard=%p for seat %p\n", ++ keyboard, seat->base); ++} ++ ++static void ++transmitter_seat_keyboard_enter(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs, ++ struct wl_array *keys) ++{ ++ struct weston_keyboard *keyboard; ++ struct wl_resource *resource = NULL; ++ struct wl_resource *surface_resource; ++ ++ keyboard = weston_seat_get_keyboard(seat->base); ++ assert(keyboard); ++ ++ assert(txs->surface); ++ surface_resource = txs->surface->resource; ++ ++ seat->keyboard_focus = txs; ++ wl_array_copy(&keyboard->keys, keys); ++ ++ wl_resource_for_each(resource, &keyboard->resource_list) { ++ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { ++ wl_keyboard_send_enter(resource, ++ serial, ++ surface_resource, ++ &keyboard->keys); ++ } ++ } ++} ++ ++static void ++transmitter_seat_keyboard_leave(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs) ++{ ++ struct weston_keyboard *keyboard; ++ struct wl_resource *resource = NULL; ++ struct wl_resource *surface_resource; ++ ++ keyboard = weston_seat_get_keyboard(seat->base); ++ assert(keyboard); ++ ++ assert(txs->surface); ++ surface_resource = txs->surface->resource; ++ ++ wl_resource_for_each(resource, &keyboard->resource_list) { ++ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { ++ wl_keyboard_send_leave(resource, ++ serial, ++ surface_resource); ++ } ++ } ++} ++ ++static void ++transmitter_seat_keyboard_key(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ uint32_t time, ++ uint32_t key, ++ uint32_t state) ++{ ++ struct weston_keyboard *keyboard; ++ struct wl_resource *resource = NULL; ++ ++ keyboard = weston_seat_get_keyboard(seat->base); ++ assert(keyboard); ++ ++ wl_resource_for_each(resource, &keyboard->resource_list) { ++ if (wl_resource_get_client(resource) == ++ wl_resource_get_client(seat->keyboard_focus->surface->resource)) { ++ wl_keyboard_send_key(resource, ++ serial, ++ time, ++ key, ++ state); ++ } ++ } ++} ++ ++static void ++transmitter_seat_create_touch(struct weston_transmitter_seat *seat) ++{ ++ struct weston_touch *touch; ++ ++ seat->touch_focus = NULL; ++ weston_seat_init_touch(seat->base); ++ ++ touch = weston_seat_get_touch(seat->base); ++ ++ touch->default_grab.interface = &touch_grab_impl; ++ ++ weston_log("Transmitter created touch=%p for seat %p\n", ++ touch, seat->base); ++} ++ ++static void ++transmitter_seat_touch_down (struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ uint32_t time, ++ struct weston_transmitter_surface *txs, ++ int32_t touch_id, ++ wl_fixed_t x, ++ wl_fixed_t y) ++{ ++ struct weston_touch *touch; ++ struct wl_resource *resource = NULL; ++ struct wl_resource *surface_resource; ++ ++ touch = weston_seat_get_touch(seat->base); ++ assert(touch); ++ ++ assert(txs->surface); ++ surface_resource = txs->surface->resource; ++ ++ seat->touch_focus = txs; ++ ++ wl_resource_for_each(resource, &touch->resource_list) { ++ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { ++ wl_touch_send_down(resource, serial, time, ++ surface_resource, ++ touch_id, x, y); ++ } ++ } ++} ++ ++static void ++transmitter_seat_touch_up (struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ uint32_t time, ++ int32_t touch_id) ++{ ++ struct weston_touch *touch; ++ struct wl_resource *resource = NULL; ++ ++ touch = weston_seat_get_touch(seat->base); ++ assert(touch); ++ ++ wl_resource_for_each(resource, &touch->resource_list) { ++ if (wl_resource_get_client(resource) == ++ wl_resource_get_client(seat->touch_focus->surface->resource)) { ++ wl_touch_send_up(resource, serial, time, touch_id); ++ } ++ } ++} ++ ++static void ++transmitter_seat_touch_motion (struct weston_transmitter_seat *seat, ++ uint32_t time, ++ int32_t touch_id, ++ wl_fixed_t x, ++ wl_fixed_t y) ++{ ++ struct weston_touch *touch; ++ struct wl_resource *resource = NULL; ++ ++ touch = weston_seat_get_touch(seat->base); ++ assert(touch); ++ ++ wl_resource_for_each(resource, &touch->resource_list) { ++ if (wl_resource_get_client(resource) == ++ wl_resource_get_client(seat->touch_focus->surface->resource)) { ++ wl_touch_send_motion(resource, time, touch_id, x, y); ++ } ++ } ++} ++ ++static void ++transmitter_seat_touch_frame (struct weston_transmitter_seat *seat) ++{ ++ struct weston_touch *touch; ++ struct wl_resource *resource = NULL; ++ ++ touch = weston_seat_get_touch(seat->base); ++ assert(touch); ++ ++ wl_resource_for_each(resource, &touch->resource_list) { ++ if (wl_resource_get_client(resource) == ++ wl_resource_get_client(seat->touch_focus->surface->resource)) { ++ wl_touch_send_frame(resource); ++ } ++ } ++} ++ ++static void ++transmitter_seat_touch_cancel (struct weston_transmitter_seat *seat) ++{ ++ struct weston_touch *touch; ++ struct wl_resource *resource = NULL; ++ ++ touch = weston_seat_get_touch(seat->base); ++ assert(touch); ++ ++ wl_resource_for_each(resource, &touch->resource_list) { ++ if (wl_resource_get_client(resource) == ++ wl_resource_get_client(seat->touch_focus->surface->resource)) { ++ wl_touch_send_cancel(resource); ++ } ++ } ++} ++ ++static char * ++make_seat_name(struct weston_transmitter_remote *remote, const char *name) ++{ ++ char *str; ++ ++ if (asprintf(&str, "transmitter-%s-%s", remote->addr, name) < 0) ++ return NULL; ++ ++ return str; ++} ++ ++void ++transmitter_seat_destroy(struct weston_transmitter_seat *seat) ++{ ++ wl_list_remove(&seat->link); ++ ++ weston_log("Transmitter destroy seat=%p\n", seat->base); ++ ++ wl_list_remove(&seat->get_pointer_listener.link); ++ wl_list_remove(&seat->pointer_focus_destroy_listener.link); ++ ++ if (seat->pointer_timer) ++ wl_event_source_remove(seat->pointer_timer); ++ ++ free(seat); ++} ++ ++static void ++pointer_handle_enter(struct wthp_pointer *wthp_pointer, ++ uint32_t serial, ++ struct wthp_surface *surface, ++ wth_fixed_t surface_x, ++ wth_fixed_t surface_y) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_pointer); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ struct weston_transmitter_surface *txs; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ if (txs->wthp_surf == surface) { ++ if (txs != seat->pointer_focus) ++ transmitter_seat_pointer_leave(seat, serial, seat->pointer_focus); ++ transmitter_seat_pointer_enter(seat, serial, txs, ++ surface_x, surface_y); ++ } ++ } ++} ++ ++static void ++pointer_handle_leave(struct wthp_pointer *wthp_pointer, ++ uint32_t serial, ++ struct wthp_surface *surface) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_pointer); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ struct weston_transmitter_surface *txs; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ if (txs->wthp_surf == surface) { ++ transmitter_seat_pointer_leave(seat, serial, txs); ++ } ++ } ++} ++ ++static void ++pointer_handle_motion(struct wthp_pointer *wthp_pointer, ++ uint32_t time, ++ wth_fixed_t surface_x, ++ wth_fixed_t surface_y) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_pointer); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_pointer_motion(seat, time, ++ surface_x, ++ surface_y); ++} ++ ++static void ++pointer_handle_button(struct wthp_pointer *wthp_pointer, ++ uint32_t serial, ++ uint32_t time, ++ uint32_t button, ++ uint32_t state) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_pointer); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_pointer_button(seat, serial, ++ time, button, ++ state); ++} ++ ++static void ++pointer_handle_axis(struct wthp_pointer *wthp_pointer, ++ uint32_t time, ++ uint32_t axis, wth_fixed_t value) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_pointer); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_pointer_axis(seat, time, ++ axis, value); ++} ++ ++static void ++pointer_handle_frame(struct wthp_pointer *wthp_pointer) ++{ ++ /* ToDo : implement pointer handle frame */ ++} ++ ++static void ++pointer_handle_axis_source(struct wthp_pointer *wthp_pointer, ++ uint32_t axis_source) ++{ ++ /* ToDo : implement pointer handle axis source */ ++} ++ ++static void ++pointer_handle_axis_stop(struct wthp_pointer *wthp_pointer, ++ uint32_t time, ++ uint32_t axis) ++{ ++ /* ToDo : implement pointer handle axis stop */ ++} ++ ++static void ++pointer_handle_axis_discrete(struct wthp_pointer *wthp_pointer, ++ uint32_t axis, ++ int32_t discrete) ++{ ++ /* ToDo : implement pointer handle axis discrete */ ++} ++ ++static const struct wthp_pointer_listener pointer_listener = { ++ pointer_handle_enter, ++ pointer_handle_leave, ++ pointer_handle_motion, ++ pointer_handle_button, ++ pointer_handle_axis, ++ pointer_handle_frame, ++ pointer_handle_axis_source, ++ pointer_handle_axis_stop, ++ pointer_handle_axis_discrete ++}; ++ ++static void ++keyboard_handle_keymap(struct wthp_keyboard * wthp_keyboard, ++ uint32_t format, ++ uint32_t keymap_sz, ++ void * keymap) ++{ ++ /* ToDo : implement keyboard handle keymap */ ++} ++ ++static void ++keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard, ++ uint32_t serial, ++ struct wthp_surface *surface, ++ struct wth_array *keys) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_keyboard); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ struct weston_transmitter_surface *txs; ++ struct wl_array *wl_key = (struct wl_array *)malloc(sizeof(struct wl_array)); ++ ++ wl_key->size = keys->size; ++ wl_key->alloc = keys->alloc; ++ wl_key->data = keys->data; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ if (txs->wthp_surf == surface) { ++ //transmitter_seat_keyboard_enter(seat, serial, txs, keys); ++ transmitter_seat_keyboard_enter(seat, serial, txs, wl_key); ++ } ++ } ++ free(wl_key); ++} ++ ++static void ++keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard, ++ uint32_t serial, ++ struct wthp_surface *surface) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_keyboard); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ struct weston_transmitter_surface *txs; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ if (txs->wthp_surf == surface) { ++ transmitter_seat_keyboard_leave(seat, serial, txs); ++ } ++ } ++} ++ ++static void ++keyboard_handle_key(struct wthp_keyboard *wthp_keyboard, ++ uint32_t serial, ++ uint32_t time, ++ uint32_t key, ++ uint32_t state) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_keyboard); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_keyboard_key(seat, serial, time, key, state); ++} ++ ++static void ++keyboard_handle_modifiers(struct wthp_keyboard *wthp_keyboard, ++ uint32_t serial, ++ uint32_t mods_depressed, ++ uint32_t mods_latched, ++ uint32_t mods_locked, ++ uint32_t group) ++{ ++ weston_log("keyboard_handle_modifiers\n"); ++} ++ ++static void ++keyboard_handle_repeat_info(struct wthp_keyboard *wthp_keyboard, ++ int32_t rate, ++ int32_t delay) ++{ ++ weston_log("keyboard_handle_repeat_info\n"); ++} ++ ++static const struct wthp_keyboard_listener keyboard_listener = { ++ keyboard_handle_keymap, ++ keyboard_handle_enter, ++ keyboard_handle_leave, ++ keyboard_handle_key, ++ keyboard_handle_modifiers, ++ keyboard_handle_repeat_info ++}; ++ ++static void ++touch_handle_down (struct wthp_touch * wthp_touch, ++ uint32_t serial, ++ uint32_t time, ++ struct wthp_surface * surface, ++ int32_t id, ++ wth_fixed_t x, ++ wth_fixed_t y) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_touch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ struct weston_transmitter_surface *txs; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ if (txs->wthp_surf == surface) { ++ transmitter_seat_touch_down(seat, serial, time, ++ txs, id, x, y); ++ } ++ } ++} ++ ++static void ++touch_handle_up (struct wthp_touch * wthp_touch, ++ uint32_t serial, ++ uint32_t time, ++ int32_t id) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_touch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_touch_up(seat, serial, time, id); ++} ++ ++static void ++touch_handle_motion (struct wthp_touch * wthp_touch, ++ uint32_t time, ++ int32_t id, ++ wth_fixed_t x, ++ wth_fixed_t y) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_touch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_touch_motion(seat, time, id, x, y); ++} ++ ++ ++static void ++touch_handle_frame (struct wthp_touch * wthp_touch) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_touch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_touch_frame(seat); ++} ++ ++static void ++touch_handle_cancel (struct wthp_touch * wthp_touch) ++{ ++ struct waltham_display *dpy = ++ wth_object_get_user_data((struct wth_object *)wthp_touch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ struct wl_list *seat_list = &remote->seat_list; ++ struct weston_transmitter_seat *seat; ++ ++ seat = wl_container_of(seat_list->next, seat, link); ++ ++ transmitter_seat_touch_cancel(seat); ++} ++ ++ ++static const struct wthp_touch_listener touch_listener = { ++ touch_handle_down, ++ touch_handle_up, ++ touch_handle_motion, ++ touch_handle_frame, ++ touch_handle_cancel ++}; ++ ++void ++seat_capabilities(struct wthp_seat *wthp_seat, ++ enum wthp_seat_capability caps) ++{ ++ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)wthp_seat); ++ ++ weston_log("seat_capabilities\n"); ++ ++ if ((caps & WTHP_SEAT_CAPABILITY_POINTER) && !dpy->pointer) ++ { ++ weston_log("WTHP_SEAT_CAPABILITY_POINTER\n"); ++ dpy->pointer = wthp_seat_get_pointer(dpy->seat); ++ wthp_pointer_set_listener(dpy->pointer, &pointer_listener, dpy); ++ } ++ if ((caps & WTHP_SEAT_CAPABILITY_KEYBOARD) && !dpy->keyboard) ++ { ++ weston_log("WTHP_SEAT_CAPABILITY_KEYBOARD\n"); ++ dpy->keyboard = wthp_seat_get_keyboard(dpy->seat); ++ wthp_keyboard_set_listener(dpy->keyboard, &keyboard_listener, dpy); ++ } ++ if ((caps & WTHP_SEAT_CAPABILITY_TOUCH) && !dpy->touch) ++ { ++ weston_log("WTHP_SEAT_CAPABILITY_TOUCH\n"); ++ dpy->touch = wthp_seat_get_touch(dpy->seat); ++ wthp_touch_set_listener(dpy->touch, &touch_listener, dpy); ++ } ++} ++ ++int ++transmitter_remote_create_seat(struct weston_transmitter_remote *remote) ++{ ++ struct weston_transmitter_seat *seat = NULL; ++ char *name = NULL; ++ struct weston_seat *weston_seat = NULL; ++ ++ seat = zalloc(sizeof *seat); ++ if (!seat) ++ goto fail; ++ ++ wl_list_init(&seat->get_pointer_listener.link); ++ wl_list_init(&seat->pointer_focus_destroy_listener.link); ++ ++ /* XXX: get the name from remote */ ++ name = make_seat_name(remote, "default"); ++ if (!name) ++ goto fail; ++ ++ ++ if (wl_list_empty(&remote->transmitter->compositor->seat_list)) { ++ weston_seat = zalloc(sizeof *weston_seat); ++ if (!weston_seat) ++ goto fail; ++ ++ weston_seat_init(weston_seat, remote->transmitter->compositor, name); ++ seat->base = weston_seat; ++ weston_log("Transmitter created seat=%p \n", &seat->base); ++ } else { ++ wl_list_for_each(weston_seat, &remote->transmitter->compositor->seat_list, link) { ++ weston_log("Transmitter weston_seat %p\n", weston_seat); ++ seat->base = weston_seat; ++ } ++ } ++ ++ free(name); ++#if DEBUG ++ weston_seat_init(&seat->base, remote->transmitter->compositor, name); ++ free(name); ++ ++ /* Hide the weston_seat from the rest of Weston, there are too many ++ * things making assumptions: ++ * - backends assume they control all seats ++ * - shells assume they control all input foci ++ * We do not want either to mess with our seat. ++ */ ++ wl_list_remove(&seat->base.link); ++ wl_list_init(&seat->base.link); ++ ++ /* The weston_compositor::seat_created_signal has already been ++ * emitted. Shells use it to subscribe to focus changes, but we should ++ * never handle focus with weston core... except maybe with keyboard. ++ * text-backend.c will also act on the new seat. ++ * It is possible weston_seat_init() needs to be split to fix this ++ * properly. ++ */ ++ ++ weston_log("Transmitter created seat=%p '%s'\n", ++ &seat->base, seat->base.seat_name); ++#endif ++ ++ /* XXX: mirror remote capabilities */ ++ transmitter_seat_create_pointer(seat); ++ transmitter_seat_create_keyboard(seat); ++ transmitter_seat_create_touch(seat); ++ ++ wl_list_insert(&remote->seat_list, &seat->link); ++ ++ return 0; ++ ++fail: ++ free(seat); ++ free(name); ++ ++ return -1; ++} ++ ++static void ++fake_pointer_get_position(struct weston_transmitter_seat *seat, double step, ++ wl_fixed_t *x, wl_fixed_t *y) ++{ ++ double s, c; ++ ++ seat->pointer_phase += step; ++ while (seat->pointer_phase > 2.0 * M_PI) ++ seat->pointer_phase -= 2.0 * M_PI; ++ ++ sincos(seat->pointer_phase, &s, &c); ++ *x = wl_fixed_from_double(100.0 + 50.0 * c); ++ *y = wl_fixed_from_double(100.0 + 50.0 * s); ++} ++ ++static int ++fake_pointer_timer_handler(void *data) ++{ ++ struct weston_transmitter_seat *seat = data; ++ wl_fixed_t x, y; ++ uint32_t time; ++ ++ time = weston_compositor_get_time(); ++ ++ fake_pointer_get_position(seat, 18.0 / 180.0 * M_PI, &x, &y); ++ transmitter_seat_pointer_motion(seat, time, x, y); ++ transmitter_seat_pointer_frame(seat); ++ ++ wl_event_source_timer_update(seat->pointer_timer, 100); ++ ++ return 0; ++} ++ ++int ++transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, ++ struct weston_transmitter_surface *txs) ++{ ++ struct wl_event_loop *loop; ++ wl_fixed_t x, y; ++ uint32_t serial = 5; ++ ++ /* remove focus from earlier surface */ ++ transmitter_seat_pointer_leave(seat, serial++, seat->pointer_focus); ++ transmitter_seat_pointer_frame(seat); ++ ++ /* set pointer focus to surface */ ++ fake_pointer_get_position(seat, 0.0, &x, &y); ++ transmitter_seat_pointer_enter(seat, serial++, txs, x, y); ++ transmitter_seat_pointer_frame(seat); ++ ++ if (!seat->pointer_timer) { ++ /* schedule timer for motion */ ++ loop = wl_display_get_event_loop(seat->base->compositor->wl_display); ++ seat->pointer_timer = wl_event_loop_add_timer(loop, ++ fake_pointer_timer_handler, seat); ++ wl_event_source_timer_update(seat->pointer_timer, 100); ++ } ++ ++ /* XXX: if the now focused surface disappears, we should call ++ * transmitter_seat_pointer_leave() as part of the mockup. Otherwise ++ * you get a "Transmitter Warning: no pointer->focus_client?". ++ */ ++ ++ return 0; ++} +diff --git a/waltham-transmitter/transmitter-plugin/output.c b/waltham-transmitter/transmitter-plugin/output.c +new file mode 100644 +index 0000000..c379ce5 +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/output.c +@@ -0,0 +1,352 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "compositor.h" ++#include "compositor-drm.h" ++#include "plugin-registry.h" ++ ++#include "plugin.h" ++#include "transmitter_api.h" ++#include "waltham-renderer.h" ++ ++/** @file ++ * ++ * This is an implementation of a remote output. ++ * ++ * A remote output must not be accepted as an argument to: ++ * - wl_shell_surface.set_fullscreen ++ * - wl_shell_surface.set_maximized ++ * - zwp_fullscreen_shell_v1.present_surface ++ * - zwp_fullscreen_shell_v1.present_surface_for_mode ++ * - zwp_input_panel_surface_v1.set_toplevel ++ * - xdg_surface.set_fullscreen ++ * ++ * If a remote output is an argument to the above or similar requests, ++ * it should have the same effect as NULL if possible. ++ * ++ * @todo Should we instead accept the argument and have it start remoting ++ * automatically? That would be shell-specific. ++ * ++ * In ivi-shell's case, only zwp_input_panel_surface_v1.set_toplevel is ++ * reachable from keyboard.c. That just blindly uses whatever the first ++ * output happens to be, so there is no need to check for now. ++ * ++ * @todo Add weston_output_set_remote() which sets weston_output::is_remote ++ * to true and inits weston_output::link. This should be made mutually ++ * exclusive with weston_compositor_add_output(). ++ */ ++ ++static struct waltham_renderer_interface *waltham_renderer; ++ ++static char * ++make_model(struct weston_transmitter_remote *remote, int name) ++{ ++ char *str; ++ ++ if (asprintf(&str, "transmitter-%s:%s-%d", remote->addr, remote->port, name) < 0) ++ return NULL; ++ ++ return str; ++} ++ ++static int ++make_mode_list(struct wl_list *list, ++ const struct weston_transmitter_output_info *info) ++{ ++ struct weston_mode *mode; ++ ++ mode = zalloc(sizeof *mode); ++ if (!mode) ++ return -1; ++ ++ *mode = info->mode; ++ wl_list_insert(list->prev, &mode->link); ++ ++ return 0; ++} ++ ++static struct weston_mode * ++get_current_mode(struct wl_list *mode_list) ++{ ++ struct weston_mode *mode; ++ ++ wl_list_for_each(mode, mode_list, link) ++ if (mode->flags & WL_OUTPUT_MODE_CURRENT) ++ return mode; ++ ++ assert(0); ++ return NULL; ++} ++ ++static void ++free_mode_list(struct wl_list *mode_list) ++{ ++ struct weston_mode *mode; ++ ++ while (!wl_list_empty(mode_list)) { ++ mode = wl_container_of(mode_list->next, mode, link); ++ ++ wl_list_remove(&mode->link); ++ free(mode); ++ } ++} ++ ++void ++transmitter_output_destroy(struct weston_transmitter_output *output) ++{ ++ wl_list_remove(&output->link); ++ ++ free_mode_list(&output->base.mode_list); ++ free(output->base.serial_number); ++ free(output->base.model); ++ free(output->base.make); ++ ++ weston_output_destroy(&output->base); ++ free(output); ++} ++ ++static void ++transmitter_output_destroy_(struct weston_output *base) ++{ ++ struct weston_transmitter_output *output = wl_container_of(base, output, base); ++ ++ transmitter_output_destroy(output); ++} ++ ++ ++static void ++transmitter_start_repaint_loop(struct weston_output *base) ++{ ++ struct timespec ts; ++ struct weston_transmitter_output *output = wl_container_of(base, output, base); ++ ++ weston_compositor_read_presentation_clock(output->base.compositor, &ts); ++ weston_output_finish_frame(&output->base, &ts, 0); ++} ++ ++static int ++transmitter_output_repaint(struct weston_output *base, ++ pixman_region32_t *damage) ++{ ++ struct weston_transmitter_output* output = wl_container_of(base, output, base); ++ struct weston_transmitter_remote* remote = output->remote; ++ struct weston_transmitter* txr = remote->transmitter; ++ struct weston_transmitter_api* transmitter_api = ++ weston_get_transmitter_api(txr->compositor); ++ struct weston_transmitter_surface* txs; ++ struct weston_compositor *compositor = base->compositor; ++ struct weston_view *view; ++ bool found_output = false; ++ struct timespec ts; ++ ++ struct weston_drm_output_api *api = ++ weston_plugin_api_get(txr->compositor, WESTON_DRM_OUTPUT_API_NAME, sizeof(api)); ++ ++ /* ++ * Pick up weston_view in transmitter_output and check weston_view's surface ++ * If the surface hasn't been conbined to weston_transmitter_surface, ++ * then call push_to_remote. ++ * If the surface has already been combined, call gather_state. ++ */ ++ if (wl_list_empty(&compositor->view_list)) ++ goto out; ++ ++ if (remote->status == WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) ++ goto out; ++ ++ wl_list_for_each_reverse(view, &compositor->view_list, link) { ++ bool found_surface = false; ++ if (view->output == &output->base) { ++ found_output = true; ++ wl_list_for_each(txs, &remote->surface_list, link) { ++ if (txs->surface == view->surface) { ++ found_surface = true; ++ if (!txs->wthp_surf) ++ transmitter_api->surface_push_to_remote ++ (view->surface, remote, NULL); ++ ++ output->renderer->dmafd = ++ api->get_dma_fd_from_view(&output->base, view); ++ if(!output->renderer->dmafd) { ++ weston_log("Failed to get dmafd\n"); ++ goto out; ++ } ++ ++ /* ++ * Updating the width x height ++ * from surface to gst-recorder ++ */ ++ output->renderer->surface_width ++ = view->surface->width; ++ output->renderer->surface_height ++ = view->surface->height; ++ ++ output->renderer->repaint_output(output); ++ output->renderer->dmafd = NULL; ++ transmitter_api->surface_gather_state(txs); ++ weston_buffer_reference(&view->surface->buffer_ref, NULL); ++ break; ++ } ++ } ++ if (!found_surface) ++ transmitter_api->surface_push_to_remote(view->surface, ++ remote, NULL); ++ } ++ } ++ if (!found_output) ++ goto out; ++ ++ weston_compositor_read_presentation_clock(output->base.compositor, &ts); ++ weston_output_finish_frame(&output->base, &ts, 0); ++ ++ return 0; ++ ++out: ++ transmitter_start_repaint_loop(base); ++ ++ return 0; ++} ++ ++static void ++transmitter_assign_planes(struct weston_output *base) { ++ /* ++ * This function prevents compositor releasing buffer early. ++ */ ++ struct weston_transmitter_output* output = wl_container_of(base, output, base); ++ struct weston_transmitter_remote* remote = output->remote; ++ struct weston_transmitter_surface* txs; ++ struct weston_compositor *compositor = base->compositor; ++ struct weston_view *view; ++ ++ wl_list_for_each_reverse(view, &compositor->view_list, link) { ++ if (view->output == &output->base) { ++ wl_list_for_each(txs, &remote->surface_list, link) { ++ if (txs->surface == view->surface) ++ view->surface->keep_buffer = true; ++ ++ } ++ } ++ } ++} ++ ++static void ++transmitter_output_enable(struct weston_output *base) ++{ ++ struct weston_transmitter_output *output = wl_container_of(base, output, base); ++ ++ output->base.assign_planes = transmitter_assign_planes; ++ output->base.set_backlight = NULL; ++ output->base.set_dpms = NULL; ++ output->base.switch_mode = NULL; ++} ++ ++int ++transmitter_remote_create_output(struct weston_transmitter_remote *remote, ++ const struct weston_transmitter_output_info *info) ++{ ++ struct weston_transmitter_output *output; ++ struct weston_transmitter *txr = remote->transmitter; ++ struct weston_output *def_output; ++ ++ output = zalloc(sizeof *output); ++ if (!output) ++ return -1; ++ ++ output->parent.draw_initial_frame = true; ++ ++ output->base.subpixel = info->subpixel; ++ ++ output->base.name = make_model(remote, 1); ++ output->base.make = strdup(WESTON_TRANSMITTER_OUTPUT_MAKE); ++ output->base.model = make_model(remote, 1); ++ output->base.serial_number = strdup("0"); ++ /* x and y is fake value */ ++ wl_list_init(&output->base.mode_list); ++ if (make_mode_list(&output->base.mode_list, info) < 0) ++ goto fail; ++ ++ output->base.current_mode = get_current_mode(&output->base.mode_list); ++ output->base.height = output->base.current_mode->height; ++ output->base.width = output->base.current_mode->width; ++ /* WL_OUTPUT_MODE_CURRENT already set */ ++ weston_output_init(&output->base, remote->transmitter->compositor); ++ ++ /* ++ * renderer_output_create skipped: ++ * no renderer awareness is needed for this output ++ */ ++ ++ /* ++ * weston_compositor_add_output() skipped: ++ * Most other code uses weston_compositor::output_list when traversing ++ * all outputs, we do not want any of that. ++ * Also weston_compositor::output_created_signal must not trigger ++ * for this output, since we must not involve input device management ++ * or color management or any kind of local management. ++ */ ++ output->base.enable = transmitter_output_enable; ++ output->base.start_repaint_loop = transmitter_start_repaint_loop; ++ output->base.repaint = transmitter_output_repaint; ++ output->base.destroy = transmitter_output_destroy_; ++ output->base.assign_planes = NULL; ++ output->base.set_dpms = NULL; ++ output->base.switch_mode = NULL; ++ output->base.gamma_size = 0; ++ output->base.set_gamma = NULL; ++ ++ output->base.native_mode = output->base.current_mode; ++ output->base.native_scale = output->base.current_scale; ++ output->base.scale = 1; ++ output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL; ++ ++ output->remote = remote; ++ wl_list_insert(&remote->output_list, &output->link); ++ ++ /* Loading a waltham renderer library */ ++ waltham_renderer = weston_load_module("waltham-renderer.so","waltham_renderer_interface"); ++ ++ if (waltham_renderer->display_create(output) < 0) { ++ weston_log("Failed to create waltham renderer display \n"); ++ return -1; ++ } ++ ++ weston_output_enable(&output->base); ++ ++ return 0; ++ ++fail: ++ free_mode_list(&output->base.mode_list); ++ free(output->base.serial_number); ++ free(output->base.model); ++ free(output->base.make); ++ free(output->base.name); ++ free(output); ++ ++ return -1; ++} +diff --git a/waltham-transmitter/transmitter-plugin/plugin.c b/waltham-transmitter/transmitter-plugin/plugin.c +new file mode 100644 +index 0000000..f643bd8 +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/plugin.c +@@ -0,0 +1,940 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "compositor.h" ++ ++#include "weston.h" ++#include "plugin.h" ++#include "transmitter_api.h" ++#include "plugin-registry.h" ++#include "ivi-layout-export.h" ++ ++/* waltham */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_EPOLL_WATCHES 2 ++#define ESTABLISH_CONNECTION_PERIOD 2000 ++#define RETRY_CONNECTION_PERIOD 5000 ++ ++/* XXX: all functions and variables with a name, and things marked with a ++ * comment, containing the word "fake" are mockups that need to be ++ * removed from the final implementation. ++ */ ++ ++/** Send configure event through ivi-shell. ++ * ++ * \param txs The Transmitter surface. ++ * \param width Suggestion for surface width. ++ * \param height Suggestion for surface height. ++ * ++ * When the networking code receives a ivi_surface.configure event, it calls ++ * this function to relay it to the application. ++ * ++ * \c txs cannot be a zombie, because transmitter_surface_zombify() must ++ * tear down the network link, so a zombie cannot receive events. ++ */ ++void ++transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, ++ int32_t width, int32_t height) ++{ ++ assert(txs->resize_handler); ++ if (!txs->resize_handler) ++ return; ++ ++ assert(txs->surface); ++ if (!txs->surface) ++ return; ++ ++ txs->resize_handler(txs->resize_handler_data, width, height); ++} ++ ++static void ++transmitter_surface_configure(struct weston_transmitter_surface *txs, ++ int32_t dx, int32_t dy) ++{ ++ assert(txs->surface); ++ if (!txs->surface) ++ return; ++ ++ txs->attach_dx += dx; ++ txs->attach_dy += dy; ++} ++ ++static void ++buffer_send_complete(struct wthp_buffer *b, uint32_t serial) ++{ ++ if (b) ++ wthp_buffer_destroy(b); ++} ++ ++static const struct wthp_buffer_listener buffer_listener = { ++ buffer_send_complete ++}; ++ ++static void ++transmitter_surface_gather_state(struct weston_transmitter_surface *txs) ++{ ++ struct weston_transmitter_remote *remote = txs->remote; ++ struct waltham_display *dpy = remote->display; ++ int ret; ++ ++ if(!dpy->running) { ++ if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) { ++ remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED; ++ wth_connection_destroy(remote->display->connection); ++ wl_event_source_remove(remote->source); ++ wl_event_source_timer_update(remote->retry_timer, 1); ++ } ++ } ++ else { ++ /* TODO: transmit surface state to remote */ ++ /* The buffer must be transmitted to remote side */ ++ ++ /* waltham */ ++ struct weston_surface *surf = txs->surface; ++ struct weston_compositor *comp = surf->compositor; ++ int32_t stride, data_sz, width, height; ++ void *data; ++ ++ width = 1; ++ height = 1; ++ stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); ++ ++ data = malloc(stride * height); ++ data_sz = stride * height; ++ ++ /* fake sending buffer */ ++ txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory, ++ data_sz, ++ data, ++ surf->width, ++ surf->height, ++ stride, ++ PIXMAN_FORMAT_BPP(comp->read_format)); ++ ++ wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs); ++ ++ wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy); ++ wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); ++ wthp_surface_commit(txs->wthp_surf); ++ ++ wth_connection_flush(remote->display->connection); ++ txs->attach_dx = 0; ++ txs->attach_dy = 0; ++ } ++} ++ ++/** Mark the weston_transmitter_surface dead. ++ * ++ * Stop all remoting actions on this surface. ++ * ++ * Still keeps the pointer stored by a shell valid, so it can be freed later. ++ */ ++static void ++transmitter_surface_zombify(struct weston_transmitter_surface *txs) ++{ ++ struct weston_transmitter_remote *remote; ++ /* may be called multiple times */ ++ if (!txs->surface) ++ return; ++ ++ wl_signal_emit(&txs->destroy_signal, txs); ++ ++ wl_list_remove(&txs->surface_destroy_listener.link); ++ txs->surface = NULL; ++ ++ wl_list_remove(&txs->sync_output_destroy_listener.link); ++ ++ remote = txs->remote; ++ if (!remote->display->compositor) ++ weston_log("remote->compositor is NULL\n"); ++ if (txs->wthp_surf) ++ wthp_surface_destroy(txs->wthp_surf); ++ if (txs->wthp_ivi_surface) ++ wthp_ivi_surface_destroy(txs->wthp_ivi_surface); ++ ++ /* In case called from destroy_transmitter() */ ++ txs->remote = NULL; ++} ++ ++static void ++transmitter_surface_destroy(struct weston_transmitter_surface *txs) ++{ ++ transmitter_surface_zombify(txs); ++ ++ wl_list_remove(&txs->link); ++ free(txs); ++} ++ ++/** weston_surface destroy signal handler */ ++static void ++transmitter_surface_destroyed(struct wl_listener *listener, void *data) ++{ ++ struct weston_transmitter_surface *txs = ++ wl_container_of(listener, txs, surface_destroy_listener); ++ ++ assert(data == txs->surface); ++ ++ transmitter_surface_zombify(txs); ++} ++ ++static void ++sync_output_destroy_handler(struct wl_listener *listener, void *data) ++{ ++ struct weston_transmitter_surface *txs; ++ ++ txs = wl_container_of(listener, txs, sync_output_destroy_listener); ++ ++ wl_list_remove(&txs->sync_output_destroy_listener.link); ++ wl_list_init(&txs->sync_output_destroy_listener.link); ++ ++ weston_surface_force_output(txs->surface, NULL); ++} ++ ++static void ++transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs) ++{ ++ struct weston_transmitter_remote *remote = txs->remote; ++ struct waltham_display *dpy = remote->display; ++ struct weston_surface *ws; ++ struct ivi_layout_surface **pp_surface = NULL; ++ struct ivi_layout_surface *ivi_surf = NULL; ++ int32_t surface_length = 0; ++ int32_t ret = 0; ++ int32_t i = 0; ++ ++ ret = txs->lyt->get_surfaces(&surface_length, &pp_surface); ++ if(!ret) ++ weston_log("No ivi_surface\n"); ++ ++ ws = txs->surface; ++ ++ for(i = 0; i < surface_length; i++) { ++ ivi_surf = pp_surface[i]; ++ if (ivi_surf->surface == ws) { ++ assert(txs->surface); ++ if (!txs->surface) ++ return; ++ if(!dpy) ++ weston_log("no content in waltham_display\n"); ++ if(!dpy->compositor) ++ weston_log("no content in compositor object\n"); ++ if(!dpy->seat) ++ weston_log("no content in seat object\n"); ++ if(!dpy->application) ++ weston_log("no content in ivi-application object\n"); ++ ++ txs->wthp_ivi_surface = wthp_ivi_application_surface_create ++ (dpy->application, ivi_surf->id_surface, txs->wthp_surf); ++ weston_log("surface ID %d\n", ivi_surf->id_surface); ++ if(!txs->wthp_ivi_surface){ ++ weston_log("Failed to create txs->ivi_surf\n"); ++ } ++ } ++ } ++ free(pp_surface); ++ pp_surface = NULL; ++} ++ ++static struct weston_transmitter_surface * ++transmitter_surface_push_to_remote(struct weston_surface *ws, ++ struct weston_transmitter_remote *remote, ++ struct wl_listener *stream_status) ++{ ++ struct weston_transmitter *txr = remote->transmitter; ++ struct weston_transmitter_surface *txs; ++ bool found = false; ++ ++ if (remote->status != WESTON_TRANSMITTER_CONNECTION_READY) ++ { ++ return NULL; ++ } ++ ++ wl_list_for_each(txs, &remote->surface_list, link) { ++ if (txs->surface == ws) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ txs = NULL; ++ txs = zalloc(sizeof (*txs)); ++ if (!txs) ++ return NULL; ++ ++ txs->remote = remote; ++ wl_signal_init(&txs->destroy_signal); ++ wl_list_insert(&remote->surface_list, &txs->link); ++ ++ txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING; ++ wl_signal_init(&txs->stream_status_signal); ++ if (stream_status) ++ wl_signal_add(&txs->stream_status_signal, stream_status); ++ ++ txs->surface = ws; ++ txs->surface_destroy_listener.notify = transmitter_surface_destroyed; ++ wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener); ++ ++ wl_list_init(&txs->sync_output_destroy_listener.link); ++ ++ wl_list_init(&txs->frame_callback_list); ++ wl_list_init(&txs->feedback_list); ++ ++ txs->lyt = weston_plugin_api_get(txr->compositor, ++ IVI_LAYOUT_API_NAME, sizeof(txs->lyt)); ++ } ++ ++ /* TODO: create the content stream connection... */ ++ if (!remote->display->compositor) ++ weston_log("remote->compositor is NULL\n"); ++ if (!txs->wthp_surf) { ++ weston_log("txs->wthp_surf is NULL\n"); ++ txs->wthp_surf = wthp_compositor_create_surface(remote->display->compositor); ++ transmitter_surface_set_ivi_id(txs); ++ } ++ ++ return txs; ++} ++ ++static enum weston_transmitter_stream_status ++transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs) ++{ ++ return txs->status; ++} ++ ++/* waltham */ ++/* The server advertises a global interface. ++ * We can store the ad for later and/or bind to it immediately ++ * if we want to. ++ * We also need to keep track of the globals we bind to, so that ++ * global_remove can be handled properly (not implemented). ++ */ ++static void ++registry_handle_global(struct wthp_registry *registry, ++ uint32_t name, ++ const char *interface, ++ uint32_t version) ++{ ++ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry); ++ ++ if (strcmp(interface, "wthp_compositor") == 0) { ++ assert(!dpy->compositor); ++ dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1); ++ /* has no events to handle */ ++ } else if (strcmp(interface, "wthp_blob_factory") == 0) { ++ assert(!dpy->blob_factory); ++ dpy->blob_factory = (struct wthp_blob_factory *)wthp_registry_bind(registry, name, interface, 1); ++ /* has no events to handle */ ++ } else if (strcmp(interface, "wthp_seat") == 0) { ++ assert(!dpy->seat); ++ dpy->seat = (struct wthp_seat *)wthp_registry_bind(registry, name, interface, 1); ++ wthp_seat_set_listener(dpy->seat, &seat_listener, dpy); ++ } else if (strcmp(interface, "wthp_ivi_application") == 0) { ++ assert(!dpy->application); ++ dpy->application = (struct wthp_ivi_application *)wthp_registry_bind(registry, name, interface, 1); ++ } ++} ++ ++/* notify connection ready */ ++static void ++conn_ready_notify(struct wl_listener *l, void *data) ++{ ++ struct weston_transmitter_remote *remote = ++ wl_container_of(l, remote, establish_listener); ++ struct weston_transmitter_output_info info = { ++ WL_OUTPUT_SUBPIXEL_NONE, ++ WL_OUTPUT_TRANSFORM_NORMAL, ++ 1, ++ 0, 0, ++ 300, 200, ++ strdup(remote->model), ++ { ++ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, ++ 800, 600, ++ 51519, ++ { NULL, NULL } ++ } ++ }; ++ if(remote->width != 0) { ++ if(remote->height != 0) { ++ info.mode.width = remote->width; ++ info.mode.height = remote->height; ++ } ++ } ++ /* Outputs and seats are dynamic, do not guarantee they are all ++ * present when signalling connection status. ++ */ ++ transmitter_remote_create_output(remote, &info); ++ transmitter_remote_create_seat(remote); ++} ++ ++/* waltham */ ++/* The server removed a global. ++ * We should destroy everything we created through that global, ++ * and destroy the objects we created by binding to it. ++ * The identification happens by global's name, so we need to keep ++ * track what names we bound. ++ * (not implemented) ++ */ ++static void ++registry_handle_global_remove(struct wthp_registry *wthp_registry, ++ uint32_t name) ++{ ++ if (wthp_registry) ++ wthp_registry_free(wthp_registry); ++} ++ ++static const struct wthp_registry_listener registry_listener = { ++ registry_handle_global, ++ registry_handle_global_remove ++}; ++ ++static void ++connection_handle_data(struct watch *w, uint32_t events) ++{ ++ struct waltham_display *dpy = wl_container_of(w, dpy, conn_watch); ++ struct weston_transmitter_remote *remote = dpy->remote; ++ int ret; ++ ++ ++ if (!dpy->running) { ++ weston_log("This server is not running yet. %s:%s\n", remote->addr, remote->port); ++ return; ++ } ++ ++ if (events & EPOLLERR) { ++ weston_log("Connection errored out.\n"); ++ dpy->running = false; ++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; ++ return; ++ } ++ ++ if (events & EPOLLOUT) { ++ /* Flush out again. If the flush completes, stop ++ * polling for writable as everything has been written. ++ */ ++ ret = wth_connection_flush(dpy->connection); ++ } ++ ++ if (events & EPOLLIN) { ++ /* Do not ignore EPROTO */ ++ ret = wth_connection_read(dpy->connection); ++ ++ if (ret < 0) { ++ weston_log("Connection read error %s:%s\n", remote->addr, remote->port); ++ perror("Connection read error\n"); ++ dpy->running = false; ++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; ++ perror("EPOLL_CTL_DEL\n"); ++ ++ return; ++ } ++ } ++ ++ if (events & EPOLLHUP) { ++ weston_log("Connection hung up.\n"); ++ dpy->running = false; ++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; ++ ++ return; ++ } ++} ++ ++static void ++waltham_mainloop(int fd, uint32_t mask, void *data) ++{ ++ struct weston_transmitter_remote *remote = data; ++ struct watch *w; ++ int ret; ++ int running_display; ++ running_display = 0; ++ ++ struct waltham_display *dpy = remote->display; ++ w = &dpy->conn_watch; ++ if (!dpy) ++ goto not_running; ++ ++ if (!dpy->connection) ++ dpy->running = false; ++ ++ if (!dpy->running) ++ goto not_running; ++ ++ running_display++; ++ /* Dispatch queued events. */ ++ ret = wth_connection_dispatch(dpy->connection); ++ if (ret < 0) { ++ dpy->running = false; ++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; ++ } ++ if (!dpy->running) ++ goto not_running; ++ ++ /* Run any application idle tasks at this point. */ ++ /* (nothing to run so far) */ ++ ++ /* Flush out buffered requests. If the Waltham socket is ++ * full, poll it for writable too, and continue flushing then. ++ */ ++ ret = wth_connection_flush(dpy->connection); ++ ++ if (0 < running_display) { ++ /* Waltham events only read in the callback, not dispatched, ++ * if the Waltham socket signalled readable. If it signalled ++ * writable, flush more. See connection_handle_data(). ++ */ ++ w->cb(w, mask); ++ } ++ ++not_running: ++ ; ++} ++ ++static int ++waltham_client_init(struct waltham_display *dpy) ++{ ++ if (!dpy) ++ return -1; ++ /* ++ * get server_address from controller (adrress is set to weston.ini) ++ */ ++ dpy->connection = wth_connect_to_server(dpy->remote->addr, dpy->remote->port); ++ if(!dpy->connection) { ++ return -2; ++ } ++ else { ++ dpy->remote->status = WESTON_TRANSMITTER_CONNECTION_READY; ++ wl_signal_emit(&dpy->remote->connection_status_signal, dpy->remote); ++ } ++ ++ dpy->conn_watch.display = dpy; ++ dpy->conn_watch.cb = connection_handle_data; ++ dpy->conn_watch.fd = wth_connection_get_fd(dpy->connection); ++ dpy->remote->source = wl_event_loop_add_fd(dpy->remote->transmitter->loop, ++ dpy->conn_watch.fd, ++ WL_EVENT_READABLE, ++ waltham_mainloop, dpy->remote); ++ ++ dpy->display = wth_connection_get_display(dpy->connection); ++ /* wth_display_set_listener() is already done by waltham, as ++ * all the events are just control messaging. ++ */ ++ ++ /* Create a registry so that we will get advertisements of the ++ * interfaces implemented by the server. ++ */ ++ dpy->registry = wth_display_get_registry(dpy->display); ++ wthp_registry_set_listener(dpy->registry, ®istry_listener, dpy); ++ ++ /* Roundtrip ensures all globals' ads have been received. */ ++ if (wth_connection_roundtrip(dpy->connection) < 0) { ++ weston_log("Roundtrip failed.\n"); ++ return -1; ++ } ++ ++ if (!dpy->compositor) { ++ weston_log("Did not find wthp_compositor, quitting.\n"); ++ return -1; ++ } ++ ++ dpy->running = true; ++ ++ return 0; ++} ++ ++static int ++establish_timer_handler(void *data) ++{ ++ struct weston_transmitter_remote *remote = data; ++ int ret; ++ ++ ret = waltham_client_init(remote->display); ++ if(ret == -2) { ++ wl_event_source_timer_update(remote->establish_timer, ++ ESTABLISH_CONNECTION_PERIOD); ++ return 0; ++ } ++ remote->status = WESTON_TRANSMITTER_CONNECTION_READY; ++ wl_signal_emit(&remote->connection_status_signal, remote); ++ return 0; ++} ++ ++static void ++init_globals(struct waltham_display *dpy) ++{ ++ dpy->compositor = NULL; ++ dpy->blob_factory = NULL; ++ dpy->seat = NULL; ++ dpy->application = NULL; ++ dpy->pointer = NULL; ++ dpy->keyboard = NULL; ++ dpy->touch = NULL; ++} ++ ++static void ++disconnect_surface(struct weston_transmitter_remote *remote) ++{ ++ struct weston_transmitter_surface *txs; ++ wl_list_for_each(txs, &remote->surface_list, link) ++ { ++ free(txs->wthp_ivi_surface); ++ txs->wthp_ivi_surface = NULL; ++ free(txs->wthp_surf); ++ txs->wthp_surf = NULL; ++ } ++} ++ ++static int ++retry_timer_handler(void *data) ++{ ++ struct weston_transmitter_remote *remote = data; ++ struct waltham_display *dpy = remote->display; ++ ++ if(!dpy->running) ++ { ++ registry_handle_global_remove(dpy->registry, 1); ++ init_globals(dpy); ++ disconnect_surface(remote); ++ wl_event_source_timer_update(remote->establish_timer, ++ ESTABLISH_CONNECTION_PERIOD); ++ ++ return 0; ++ } ++ else ++ wl_event_source_timer_update(remote->retry_timer, ++ RETRY_CONNECTION_PERIOD); ++ return 0; ++} ++ ++static struct weston_transmitter_remote * ++transmitter_connect_to_remote(struct weston_transmitter *txr) ++{ ++ struct weston_transmitter_remote *remote; ++ struct wl_event_loop *loop_est, *loop_retry; ++ int ret; ++ ++ wl_list_for_each_reverse(remote, &txr->remote_list, link) { ++ /* XXX: actually start connecting */ ++ /* waltham */ ++ remote->display = zalloc(sizeof *remote->display); ++ if (!remote->display) ++ return NULL; ++ remote->display->remote = remote; ++ /* set connection establish timer */ ++ loop_est = wl_display_get_event_loop(txr->compositor->wl_display); ++ remote->establish_timer = ++ wl_event_loop_add_timer(loop_est, establish_timer_handler, remote); ++ wl_event_source_timer_update(remote->establish_timer, 1); ++ /* set connection retry timer */ ++ loop_retry = wl_display_get_event_loop(txr->compositor->wl_display); ++ remote->retry_timer = ++ wl_event_loop_add_timer(loop_retry, retry_timer_handler, remote); ++ if (ret < 0) { ++ weston_log("Fatal: Transmitter waltham connecting failed.\n"); ++ return NULL; ++ } ++ wl_signal_emit(&remote->conn_establish_signal, NULL); ++ } ++ ++ return remote; ++} ++ ++static enum weston_transmitter_connection_status ++transmitter_remote_get_status(struct weston_transmitter_remote *remote) ++{ ++ return remote->status; ++} ++ ++static void ++transmitter_remote_destroy(struct weston_transmitter_remote *remote) ++{ ++ struct weston_transmitter_surface *txs; ++ struct weston_transmitter_output *output, *otmp; ++ struct weston_transmitter_seat *seat, *stmp; ++ ++ /* Do not emit connection_status_signal. */ ++ ++ /* ++ * Must not touch remote->transmitter as it may be stale: ++ * the desctruction order between the shell and Transmitter is ++ * undefined. ++ */ ++ ++ if (!wl_list_empty(&remote->surface_list)) ++ weston_log("Transmitter warning: surfaces remain in %s.\n", ++ __func__); ++ wl_list_for_each(txs, &remote->surface_list, link) ++ txs->remote = NULL; ++ wl_list_remove(&remote->surface_list); ++ ++ wl_list_for_each_safe(seat, stmp, &remote->seat_list, link) ++ transmitter_seat_destroy(seat); ++ ++ wl_list_for_each_safe(output, otmp, &remote->output_list, link) ++ transmitter_output_destroy(output); ++ ++ free(remote->addr); ++ wl_list_remove(&remote->link); ++ ++ wl_event_source_remove(remote->source); ++ ++ free(remote); ++} ++ ++/** Transmitter is destroyed on compositor shutdown. */ ++static void ++transmitter_compositor_destroyed(struct wl_listener *listener, void *data) ++{ ++ struct weston_transmitter_remote *remote; ++ struct weston_transmitter_surface *txs; ++ struct weston_transmitter *txr = ++ wl_container_of(listener, txr, compositor_destroy_listener); ++ ++ assert(data == txr->compositor); ++ ++ /* may be called before or after shell cleans up */ ++ wl_list_for_each(remote, &txr->remote_list, link) { ++ wl_list_for_each(txs, &remote->surface_list, link) { ++ transmitter_surface_zombify(txs); ++ } ++ } ++ ++ /* ++ * Remove the head in case the list is not empty, to avoid ++ * transmitter_remote_destroy() accessing freed memory if the shell ++ * cleans up after Transmitter. ++ */ ++ wl_list_remove(&txr->remote_list); ++ ++ free(txr); ++} ++ ++static struct weston_transmitter * ++transmitter_get(struct weston_compositor *compositor) ++{ ++ struct wl_listener *listener; ++ struct weston_transmitter *txr; ++ ++ listener = wl_signal_get(&compositor->destroy_signal, ++ transmitter_compositor_destroyed); ++ if (!listener) ++ return NULL; ++ ++ txr = wl_container_of(listener, txr, compositor_destroy_listener); ++ assert(compositor == txr->compositor); ++ ++ return txr; ++} ++ ++static void ++transmitter_register_connection_status(struct weston_transmitter *txr, ++ struct wl_listener *connected_listener) ++{ ++ wl_signal_add(&txr->connected_signal, connected_listener); ++} ++ ++static struct weston_surface * ++transmitter_get_weston_surface(struct weston_transmitter_surface *txs) ++{ ++ return txs->surface; ++} ++ ++static const struct weston_transmitter_api transmitter_api_impl = { ++ transmitter_get, ++ transmitter_connect_to_remote, ++ transmitter_remote_get_status, ++ transmitter_remote_destroy, ++ transmitter_surface_push_to_remote, ++ transmitter_surface_get_stream_status, ++ transmitter_surface_destroy, ++ transmitter_surface_configure, ++ transmitter_surface_gather_state, ++ transmitter_register_connection_status, ++ transmitter_get_weston_surface, ++}; ++ ++static void ++transmitter_surface_set_resize_callback( ++ struct weston_transmitter_surface *txs, ++ weston_transmitter_ivi_resize_handler_t cb, ++ void *data) ++{ ++ txs->resize_handler = cb; ++ txs->resize_handler_data = data; ++} ++ ++static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = { ++ transmitter_surface_set_resize_callback, ++}; ++ ++static int ++transmitter_create_remote(struct weston_transmitter *txr, ++ const char *model, ++ const char *addr, ++ const char *port, ++ const char *width, ++ const char *height) ++{ ++ struct weston_transmitter_remote *remote; ++ ++ remote = zalloc(sizeof (*remote)); ++ if (!remote) ++ return -1; ++ ++ remote->transmitter = txr; ++ wl_list_insert(&txr->remote_list, &remote->link); ++ remote->model = strdup(model); ++ remote->addr = strdup(addr); ++ remote->port = strdup(port); ++ remote->width = atoi(width); ++ remote->height = atoi(height); ++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; ++ wl_signal_init(&remote->connection_status_signal); ++ wl_list_init(&remote->output_list); ++ wl_list_init(&remote->surface_list); ++ wl_list_init(&remote->seat_list); ++ wl_signal_init(&remote->conn_establish_signal); ++ remote->establish_listener.notify = conn_ready_notify; ++ wl_signal_add(&remote->conn_establish_signal, &remote->establish_listener); ++ ++ return 0; ++} ++ ++struct wet_compositor { ++ struct weston_config *config; ++ struct wet_output_config *parsed_options; ++ struct wl_listener pending_output_listener; ++ bool drm_use_current_mode; ++}; ++ ++static void ++transmitter_get_server_config(struct weston_transmitter *txr) ++{ ++ struct wet_compositor *compositor = ++ (struct wet_compositor *)weston_compositor_get_user_data(txr->compositor); ++ struct weston_config *config = wet_get_config(txr->compositor); ++ struct weston_config_section *section; ++ const char *name = NULL; ++ char *model = NULL; ++ char *addr = NULL; ++ char *port = NULL; ++ char *width = '0'; ++ char *height = '0'; ++ int ret; ++ ++ section = weston_config_get_section(config, "remote", NULL, NULL); ++ ++ while (weston_config_next_section(config, §ion, &name)) { ++ if (0 == strcmp(name, "remote-output")) { ++ if (0 != weston_config_section_get_string(section, "output-name", ++ &model, 0)) ++ continue; ++ ++ if (0 != weston_config_section_get_string(section, "server-address", ++ &addr, 0)) ++ continue; ++ ++ if (0 != weston_config_section_get_string(section, "port", ++ &port, 0)) ++ continue; ++ ++ if (0 != weston_config_section_get_string(section, "width", ++ &width, 0)) ++ continue; ++ ++ if (0 != weston_config_section_get_string(section, "height", ++ &height, 0)) ++ continue; ++ ret = transmitter_create_remote(txr, model, addr, ++ port, width, height); ++ if (ret < 0) { ++ weston_log("Fatal: Transmitter create_remote failed.\n"); ++ } ++ } ++ } ++} ++ ++WL_EXPORT int ++wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) ++{ ++ struct weston_transmitter *txr; ++ int ret; ++ ++ txr = zalloc(sizeof *txr); ++ if (!txr){ ++ weston_log("Transmitter disabled\n"); ++ return -1; ++ } ++ wl_list_init(&txr->remote_list); ++ ++ txr->compositor = compositor; ++ txr->compositor_destroy_listener.notify = ++ transmitter_compositor_destroyed; ++ wl_signal_add(&compositor->destroy_signal, ++ &txr->compositor_destroy_listener); ++ ++ ret = weston_plugin_api_register(compositor, ++ WESTON_TRANSMITTER_API_NAME, ++ &transmitter_api_impl, ++ sizeof(transmitter_api_impl)); ++ if (ret < 0) { ++ weston_log("Fatal: Transmitter API registration failed.\n"); ++ goto fail; ++ } ++ ++ ret = weston_plugin_api_register(compositor, ++ WESTON_TRANSMITTER_IVI_API_NAME, ++ &transmitter_ivi_api_impl, ++ sizeof(transmitter_ivi_api_impl)); ++ if (ret < 0) { ++ weston_log("Fatal: Transmitter IVI API registration failed.\n"); ++ goto fail; ++ } ++ ++ weston_log("Transmitter initialized.\n"); ++ ++ txr->loop = wl_display_get_event_loop(compositor->wl_display); ++ transmitter_get_server_config(txr); ++ transmitter_connect_to_remote(txr); ++ ++ return 0; ++ ++fail: ++ wl_list_remove(&txr->compositor_destroy_listener.link); ++ free(txr); ++ ++ return -1; ++} +diff --git a/waltham-transmitter/transmitter-plugin/plugin.h b/waltham-transmitter/transmitter-plugin/plugin.h +new file mode 100644 +index 0000000..a473dab +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/plugin.h +@@ -0,0 +1,330 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef WESTON_TRANSMITTER_PLUGIN_H ++#define WESTON_TRANSMITTER_PLUGIN_H ++ ++/* XXX: all functions and variables with a name, and things marked with a ++ * comment, containing the word "fake" are mockups that need to be ++ * removed from the final implementation. ++ */ ++ ++#include ++#include ++ ++#include "compositor.h" ++#include "transmitter_api.h" ++#include "ivi-layout-export.h" ++ ++#include ++ ++ ++struct waltham_display; ++ ++enum wthp_seat_capability { ++ /** ++ * the seat has pointer devices ++ */ ++ WTHP_SEAT_CAPABILITY_POINTER = 1, ++ /** ++ * the seat has one or more keyboards ++ */ ++ WTHP_SEAT_CAPABILITY_KEYBOARD = 2, ++ /** ++ * the seat has touch devices ++ */ ++ WTHP_SEAT_CAPABILITY_TOUCH = 4, ++}; ++ ++/* epoll structure */ ++struct watch { ++ struct waltham_display *display; ++ int fd; ++ void (*cb)(struct watch *w, uint32_t events); ++}; ++ ++struct waltham_display { ++ struct wth_connection *connection; ++ struct watch conn_watch; ++ struct wth_display *display; ++ ++ bool running; ++ ++ struct wthp_registry *registry; ++ ++ struct wthp_callback *bling; ++ ++ struct wthp_compositor *compositor; ++ struct wthp_blob_factory *blob_factory; ++ struct wthp_seat *seat; ++ struct wthp_pointer *pointer; ++ struct wthp_keyboard *keyboard; ++ struct wthp_touch *touch; ++ struct wthp_ivi_application *application; ++ struct wtimer *fiddle_timer; ++ ++ struct weston_transmitter_remote *remote; ++ char *addr; ++ char *port; ++}; ++ ++/* a timerfd based timer */ ++struct wtimer { ++ struct watch watch; ++ void (*func)(struct wtimer *, void *); ++ void *data; ++}; ++ ++struct weston_transmitter { ++ struct weston_compositor *compositor; ++ struct wl_listener compositor_destroy_listener; ++ ++ struct wl_list remote_list; /* transmitter_remote::link */ ++ ++ struct wl_listener stream_listener; ++ struct wl_signal connected_signal; ++ struct wl_event_loop *loop; ++}; ++ ++struct weston_transmitter_remote { ++ struct weston_transmitter *transmitter; ++ struct wl_list link; ++ char *model; ++ char *addr; ++ char *port; ++ int32_t width; ++ int32_t height; ++ ++ enum weston_transmitter_connection_status status; ++ struct wl_signal connection_status_signal; ++ struct wl_signal conn_establish_signal; ++ ++ struct wl_list output_list; /* weston_transmitter_output::link */ ++ struct wl_list surface_list; /* weston_transmitter_surface::link */ ++ struct wl_list seat_list; /* weston_transmitter_seat::link */ ++ ++ struct wl_listener establish_listener; ++ ++ struct wl_event_source *establish_timer; /* for establish connection */ ++ struct wl_event_source *retry_timer; /* for retry connection */ ++ ++ struct waltham_display *display; /* waltham */ ++ struct wl_event_source *source; ++}; ++ ++ ++struct weston_transmitter_surface { ++ struct weston_transmitter_remote *remote; ++ struct wl_list link; /* weston_transmitter_remote::surface_list */ ++ struct wl_signal destroy_signal; /* data: weston_transmitter_surface */ ++ ++ enum weston_transmitter_stream_status status; ++ struct wl_signal stream_status_signal; ++ ++ struct weston_surface *surface; ++ struct wl_listener surface_destroy_listener; ++ const struct ivi_layout_interface *lyt; ++ ++ weston_transmitter_ivi_resize_handler_t resize_handler; ++ void *resize_handler_data; ++ ++ struct weston_output *sync_output; ++ struct wl_listener sync_output_destroy_listener; ++ ++ int32_t attach_dx; /**< wl_surface.attach(buffer, dx, dy) */ ++ int32_t attach_dy; /**< wl_surface.attach(buffer, dx, dy) */ ++ struct wl_list frame_callback_list; /* weston_frame_callback::link */ ++ struct wl_list feedback_list; /* weston_presentation_feedback::link */ ++ ++ /* waltham */ ++ struct wthp_surface *wthp_surf; ++ struct wthp_blob_factory *wthp_blob; ++ struct wthp_buffer *wthp_buf; ++ struct wthp_ivi_surface *wthp_ivi_surface; ++ struct wthp_ivi_application *wthp_ivi_application; ++}; ++ ++struct weston_transmitter_output_info { ++ uint32_t subpixel; /* enum wl_output_subpixel */ ++ uint32_t transform; /* enum wl_output_transform */ ++ int32_t scale; ++ int32_t x; ++ int32_t y; ++ int32_t width_mm; ++ int32_t height_mm; ++ /* char *make; is WESTON_TRANSMITTER_OUTPUT_MAKE */ ++ char *model; ++ ++ struct weston_mode mode; ++}; ++ ++struct weston_transmitter_output { ++ struct weston_output base; ++ ++ struct { ++ bool draw_initial_frame; ++ struct wl_surface *surface; ++ struct wl_output *output; ++ struct wl_display *display; ++ int configure_width, configure_height; ++ bool wait_for_configure; ++ } parent; ++ ++ struct weston_transmitter_remote *remote; ++ struct wl_list link; /* weston_transmitter_remote::output_list */ ++ ++ struct frame *frame; ++ ++ struct wl_callback *frame_cb; ++ struct renderer *renderer; ++}; ++ ++struct weston_transmitter_seat { ++ struct weston_seat *base; ++ struct wl_list link; ++ ++ /* pointer */ ++ wl_fixed_t pointer_surface_x; ++ wl_fixed_t pointer_surface_y; ++ ++ struct wl_listener get_pointer_listener; ++ struct weston_transmitter_surface *pointer_focus; ++ struct wl_listener pointer_focus_destroy_listener; ++ ++ struct wl_event_source *pointer_timer; /* fake */ ++ ++ double pointer_phase; /* fake */ ++ ++ /* keyboard */ ++ struct weston_transmitter_surface *keyboard_focus; ++ ++ /* touch */ ++ struct weston_transmitter_surface *touch_focus; ++}; ++ ++struct ivi_layout_surface { ++ struct wl_list link; /* ivi_layout::surface_list */ ++ struct wl_signal property_changed; ++ int32_t update_count; ++ uint32_t id_surface; ++ ++ struct ivi_layout *layout; ++ struct weston_surface *surface; ++ ++ struct ivi_layout_surface_properties prop; ++ ++ struct { ++ struct ivi_layout_surface_properties prop; ++ } pending; ++ ++ struct wl_list view_list; /* ivi_layout_view::surf_link */ ++}; ++ ++void ++transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, ++ int32_t width, int32_t height); ++ ++int ++transmitter_remote_create_output(struct weston_transmitter_remote *remote, ++ const struct weston_transmitter_output_info *info); ++ ++void ++transmitter_output_destroy(struct weston_transmitter_output *output); ++ ++int ++transmitter_remote_create_seat(struct weston_transmitter_remote *remote); ++ ++void ++transmitter_seat_destroy(struct weston_transmitter_seat *seat); ++ ++/* The below are the functions to be called from the network protocol ++ * input event handlers. ++ */ ++ ++void ++transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs, ++ wl_fixed_t surface_x, ++ wl_fixed_t surface_y); ++ ++void ++transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ struct weston_transmitter_surface *txs); ++ ++void ++transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ wl_fixed_t surface_x, ++ wl_fixed_t surface_y); ++ ++void ++transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, ++ uint32_t serial, ++ uint32_t time, ++ uint32_t button, ++ uint32_t state); ++ ++void ++transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ uint32_t axis, ++ wl_fixed_t value); ++ ++void ++transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat); ++ ++void ++transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, ++ uint32_t axis_source); ++ ++void ++transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, ++ uint32_t time, ++ uint32_t axis); ++ ++void ++transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, ++ uint32_t axis, ++ int32_t discrete); ++ ++/* Fake functions for mockup testing: */ ++ ++int ++transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, ++ struct weston_transmitter_surface *txs); ++ ++void ++seat_capabilities(struct wthp_seat *wthp_seat, ++ enum wthp_seat_capability caps); ++ ++static const struct wthp_seat_listener seat_listener = { ++ seat_capabilities, ++ NULL ++}; ++ ++ ++#endif /* WESTON_TRANSMITTER_PLUGIN_H */ +diff --git a/waltham-transmitter/transmitter-plugin/transmitter_api.h b/waltham-transmitter/transmitter-plugin/transmitter_api.h +new file mode 100644 +index 0000000..9b3e5fe +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/transmitter_api.h +@@ -0,0 +1,278 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef WESTON_TRANSMITTER_API_H ++#define WESTON_TRANSMITTER_API_H ++ ++#include "plugin-registry.h" ++ ++#include ++ ++/** \file ++ * ++ * This is the Transmitter API published via weston_plugin_api_register(). ++ */ ++ ++struct weston_transmitter; ++struct weston_transmitter_remote; ++struct weston_transmitter_surface; ++ ++#define WESTON_TRANSMITTER_API_NAME "transmitter_v1" ++ ++/** See weston_transmitter_api::remote_get_status */ ++enum weston_transmitter_connection_status { ++ /** The connection hand-shake is not yet complete */ ++ WESTON_TRANSMITTER_CONNECTION_INITIALIZING, ++ ++ /** The connection is live and ready to be used. */ ++ WESTON_TRANSMITTER_CONNECTION_READY, ++ ++ /** The connection is dead. */ ++ WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, ++}; ++ ++/** See weston_transmitter_api::surface_get_stream_status */ ++enum weston_transmitter_stream_status { ++ /** The stream hand-shake is not yet complete. */ ++ WESTON_TRANSMITTER_STREAM_INITIALIZING, ++ ++ /** The stream is carrying surface content updates as needed. */ ++ WESTON_TRANSMITTER_STREAM_LIVE, ++ ++ /** The stream has failed and disconnected permanently. */ ++ WESTON_TRANSMITTER_STREAM_FAILED, ++}; ++ ++/** The Transmitter Base API ++ * ++ * Transmitter is a Weston plugin that provides remoting of weston_surfaces ++ * over the network. Shells use this API to create remote connections and ++ * push surfaces over the network. Shells are also responsible for relaying ++ * basic window state changes to Transmitter. ++ * ++ * In addition to the Transmitter Base API, shells also need to use a ++ * shell protocol specific Transmitter API to relay specific window state ++ * changes. ++ */ ++struct weston_transmitter_api { ++ /** Fetch the Transmitter plugin context ++ * ++ * \param compositor The compositor instance. ++ * \return The weston_transmitter context, which is always the same ++ * for the given compositor instance. ++ */ ++ struct weston_transmitter * ++ (*transmitter_get)(struct weston_compositor *compositor); ++ ++ /** ++ * Connect to a remote server via Transmitter. ++ * ++ * \param txr The Transmitter context. ++ * \param status Listener to inform of connection status changes. ++ * \return A handle to the remote connection, or NULL on failure. ++ * ++ * This call attempts to open a connection asynchronously. The ++ * connection is not usable until the listener signals it is ready. ++ * The listener may also signal that the connection failed instead. ++ * ++ * The listener callback argument is the weston_transmitter_remote ++ * returned by this function. Use remote_get_status() to fetch the ++ * current status. ++ * ++ */ ++ struct weston_transmitter_remote * ++ (*connect_to_remote)(struct weston_transmitter *txr); ++ ++ /** ++ * Retrieve the connection status. ++ * ++ * If the status is WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, ++ * you have to shut the remote down completely. There is no automatic ++ * reconnect. ++ */ ++ enum weston_transmitter_connection_status ++ (*remote_get_status)(struct weston_transmitter_remote *remote); ++ ++ /** ++ * Destroy/disconnect a remote connection. ++ * ++ * Disconnects if connected, and destroys the connection. ++ * The connection status handler is not called. ++ * ++ * The caller is responsible for destroying all ++ * weston_transmitter_surfaces before calling this. ++ */ ++ void ++ (*remote_destroy)(struct weston_transmitter_remote *remote); ++ ++ /** Push a weston_surface to be transmitted to a remote. ++ * ++ * \param ws The surface to push. ++ * \param remote The remote connection to use. ++ * \param stream_status Listener for stream status changes. ++ * \return The Transmitter surface handle. ++ * ++ * The surface cannot be visible on the remote until the stream ++ * status listener signals WESTON_TRANSMITTER_STREAM_LIVE. After that, ++ * surface updates made by the application will be automatically ++ * streamed to the remote, and input events from the remote will be ++ * delivered to the application. ++ * ++ * The listener callback argument is the weston_transmitter_surface ++ * returned by this function. Use surface_get_stream_status() to ++ * fetch the current status. ++ */ ++ struct weston_transmitter_surface * ++ (*surface_push_to_remote)(struct weston_surface *ws, ++ struct weston_transmitter_remote *remote, ++ struct wl_listener *stream_status); ++ ++ /** ++ * Retrieve the surface content stream status. ++ * ++ * If the status is WESTON_TRANSMITTER_STREAM_FAILED, remoting the ++ * surface has stopped. There is no automatic retry. ++ */ ++ enum weston_transmitter_stream_status ++ (*surface_get_stream_status)(struct weston_transmitter_surface *txs); ++ ++ /** Stop remoting a weston_surface ++ * ++ * \param txs Transmitter surface handle to be stopped and freed. ++ * ++ * The surface stream status handler is not called. ++ */ ++ void ++ (*surface_destroy)(struct weston_transmitter_surface *txs); ++ ++ /** Notify of weston_surface being configured ++ * ++ * \param txs The Transmitter surface handle. ++ * \param dx The x delta given in wl_surface.attach request. ++ * \param dy The y delta given in wl_surface.attach request. ++ * ++ * Notifies Transmitter of new surface confguration. Transmitter will ++ * forward the arguments, window state, and reference the buffer for ++ * image transmission. ++ * ++ * Shells are meant to call this function for remoted surfaces in ++ * the weston_surface::configure handler. ++ * ++ * XXX: Is this necessary if we have weston_surface::apply_state_signal? ++ * ++ * Essentially this is just an elaborate way to forward dx,dy. ++ */ ++ void ++ (*surface_configure)(struct weston_transmitter_surface *txs, ++ int32_t dx, int32_t dy); ++ ++ void ++ (*surface_gather_state)(struct weston_transmitter_surface *txs); ++ ++ /** Notify that surface is connected to receiver ++ * ++ * \param txr The Transmitter context. ++ * \param connected_listener Listener for connected_signal. ++ */ ++ void ++ (*register_connection_status)(struct weston_transmitter *txr, ++ struct wl_listener *connected_listener); ++ ++ /** get weston_surface from weston_transmitter_surface ++ * ++ * \param txs The Transmitter surface. ++ */ ++ struct weston_surface * ++ (*get_weston_surface)(struct weston_transmitter_surface *txs); ++}; ++ ++static inline const struct weston_transmitter_api * ++weston_get_transmitter_api(struct weston_compositor *compositor) ++{ ++ return weston_plugin_api_get(compositor, WESTON_TRANSMITTER_API_NAME, ++ sizeof(struct weston_transmitter_api)); ++} ++ ++#define WESTON_TRANSMITTER_IVI_API_NAME "transmitter_ivi_v1" ++ ++/** For relaying configure events from Transmitter to shell. */ ++typedef void (*weston_transmitter_ivi_resize_handler_t)(void *data, ++ int32_t width, ++ int32_t height); ++ ++/** The Transmitter IVI-shell API ++ * ++ * Contains the IVI-shell specifics required to remote an ivi-surface. ++ */ ++struct weston_transmitter_ivi_api { ++ /** Set IVI-id for a transmitter surface ++ * ++ * \param txs The transmitted surface. ++ * \param ivi_id The IVI-surface id as specified by the ++ * ivi_application.surface_create request. ++ */ ++ void ++ (*set_ivi_id)(struct weston_transmitter_surface *txs, uint32_t ivi_id); ++ ++ /** Set callback to relay configure events. ++ * ++ * \param txs The transmitted surface. ++ * \param cb The callback function pointer. ++ * \param data User data to be passed to the callback. ++ * ++ * The arguments to the callback function are user data, and width and ++ * height from the configure event from the remote compositor. The ++ * shell must relay this event to the application. ++ */ ++ void ++ (*set_resize_callback)(struct weston_transmitter_surface *txs, ++ weston_transmitter_ivi_resize_handler_t cb, ++ void *data); ++}; ++ ++static inline const struct weston_transmitter_ivi_api * ++weston_get_transmitter_ivi_api(struct weston_compositor *compositor) ++{ ++ return weston_plugin_api_get(compositor, ++ WESTON_TRANSMITTER_IVI_API_NAME, ++ sizeof(struct weston_transmitter_ivi_api)); ++} ++ ++/** Identifies outputs created by the Transmitter by make */ ++#define WESTON_TRANSMITTER_OUTPUT_MAKE "Weston-Transmitter" ++ ++/* Remote compositor/output are identified by model */ ++ ++ ++struct renderer { ++ void (*repaint_output)(struct weston_output *base); ++ struct GstAppContext *ctx; ++ int32_t dmafd; /* dmafd received from compositor-drm */ ++ int surface_width; ++ int surface_height; ++ bool recorder_enabled; ++}; ++ ++#endif /* WESTON_TRANSMITTER_API_H */ +diff --git a/waltham-transmitter/transmitter-plugin/weston.ini.transmitter b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter +new file mode 100644 +index 0000000..1aff0b2 +--- /dev/null ++++ b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter +@@ -0,0 +1,21 @@ ++[core] ++shell=ivi-shell.so ++modules=transmitter.so ++ ++[ivi-shell] ++ivi-module=ivi-controller.so ++ivi-input-module=ivi-input-controller.so ++ ++[remote-output] ++output-name=transmitter_1 ++server-address=192.168.2.11 ++port=34400 ++width=1920 ++height=1080 ++ ++[remote-output] ++output-name=transmitter_2 ++server-address=192.168.2.12 ++port=34400 ++width=1920 ++height=1080 +diff --git a/waltham-transmitter/waltham-renderer/CMakeLists.txt b/waltham-transmitter/waltham-renderer/CMakeLists.txt +new file mode 100644 +index 0000000..abf1a4c +--- /dev/null ++++ b/waltham-transmitter/waltham-renderer/CMakeLists.txt +@@ -0,0 +1,59 @@ ++project (waltham-renderer) ++ ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) ++pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) ++pkg_check_modules(PIXMAN pixman-1 REQUIRED) ++pkg_check_modules(WALTHAM waltham REQUIRED) ++pkg_search_module(GSTREAMER gstreamer-1.0 required) ++pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required) ++ ++include_directories( ++ ${CMAKE_SOURCE_DIR}/waltham-transmitter/transmitter-plugin ++ ${CMAKE_CURRENT_BINARY_DIR} ++ ${WAYLAND_CLIENT_INCLUDE_DIRS} ++ ${WAYLAND_SERVER_INCLUDE_DIRS} ++ ${WESTON_INCLUDE_DIRS} ++ ${PIXMAN_INCLUDE_DIRS} ++ ${WALTHAM_INCLUDE_DIRS} ++ ${GSTREAMER_INCLUDE_DIRS} ++ ${GSTREAMERAPP_INCLUDE_DIRS} ++) ++ ++link_directories( ++ ${WAYLAND_SERVER_LIBRARY_DIRS} ++ ${WESTON_LIBRARY_DIRS} ++ ${PIXMAN_LIBRARY_DIRS} ++ ${WALTHAM_LIBRARY_DIRS} ++ ${GSTREAMER_LIBRARY_DIRS} ++ ${GSTREAMERAPP_LIBRARY_DIRS} ++) ++ ++add_library(${PROJECT_NAME} MODULE ++ waltham-renderer.c ++ waltham-renderer.h ++) ++ ++set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") ++ ++set(LIBS ++ m ++ weston-2 ++ gstallocators-1.0 ++ gstvideo-1.0 ++ ${WAYLAND_SERVER_LIBRARIES} ++ ${WESTON_LIBRARIES} ++ ${PIXMAN_LIBRARIES} ++ ${WALTHAM_LIBRARIES} ++ ${GSTREAMER_LIBRARIES} ++ ${GSTREAMERAPP_LIBRARIES} ++) ++ ++add_dependencies(${PROJECT_NAME} ${LIBS}) ++ ++target_link_libraries(${PROJECT_NAME} ${LIBS}) ++ ++install ( ++ TARGETS ${PROJECT_NAME} ++ LIBRARY DESTINATION lib64/libweston-2 ++) +diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.c b/waltham-transmitter/waltham-renderer/waltham-renderer.c +new file mode 100644 +index 0000000..16ad3f8 +--- /dev/null ++++ b/waltham-transmitter/waltham-renderer/waltham-renderer.c +@@ -0,0 +1,270 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "compositor.h" ++ ++#include "transmitter_api.h" ++#include "waltham-renderer.h" ++#include "plugin.h" ++ ++struct waltham_renderer { ++ struct renderer base; ++}; ++ ++struct GstAppContext ++{ ++ GMainLoop *loop; ++ GstBus *bus; ++ GstElement *pipeline; ++ GstElement *appsrc; ++ GstBuffer *gstbuffer; ++}; ++ ++gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) ++{ ++ struct GstAppContext *gstctx = p; ++ ++ switch( GST_MESSAGE_TYPE(message)) { ++ case GST_MESSAGE_ERROR: ++ { ++ GError *err; ++ gchar *debug; ++ ++ gst_message_parse_error(message, &err, &debug); ++ g_print("ERROR: %s\n", err->message); ++ ++ g_error_free(err); ++ g_free(debug); ++ g_main_loop_quit(gstctx->loop); ++ break; ++ } ++ ++ case GST_MESSAGE_STATE_CHANGED: ++ { ++ GstState oldstate, newstate; ++ ++ gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); ++ switch (newstate){ ++ case GST_STATE_NULL: ++ fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); ++ } ++ break; ++ } ++ default: ++ fprintf(stderr, "Unhandled message\n"); ++ break; ++ } ++} ++ ++static int ++gst_pipe_init(struct weston_transmitter_output *output, struct gst_settings *settings) ++{ ++ struct GstAppContext *gstctx; ++ gstctx=zalloc(sizeof (*gstctx)); ++ if(!gstctx){ ++ weston_log("Enable to allocate memory\n"); ++ return -1; ++ } ++ GstCaps *caps; ++ int ret = 0; ++ GError *gerror = NULL; ++ FILE * pFile; ++ long lSize; ++ char * pipe = NULL; ++ size_t res; ++ ++ /* create gstreamer pipeline */ ++ gst_init(NULL, NULL); ++ gstctx->loop = g_main_loop_new(NULL, FALSE); ++ ++ /* read pipeline from file */ ++ pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); ++ if (pFile==NULL) ++ { ++ weston_log("File open error\n"); ++ return -1; ++ } ++ ++ /* obtain file size */ ++ fseek (pFile , 0 , SEEK_END); ++ lSize = ftell (pFile); ++ rewind (pFile); ++ ++ /* allocate memory to contain the whole file: */ ++ pipe = (char*) zalloc (sizeof(char)*lSize); ++ if (pipe == NULL) ++ { ++ weston_log("Cannot allocate memory\n"); ++ return -1; ++ } ++ ++ /* copy the file into the buffer: */ ++ res = fread (pipe,1,lSize,pFile); ++ if (res != lSize) ++ { ++ weston_log("File read error\n"); ++ return -1; ++ } ++ ++ /* close file */ ++ fclose (pFile); ++ weston_log("Parsing GST pipeline:%s",pipe); ++ gstctx->pipeline = gst_parse_launch(pipe, &gerror); ++ free(pipe); ++ if(!gstctx->pipeline) ++ weston_log("Could not create gstreamer pipeline.\n"); ++ ++ gstctx->bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx->pipeline)); ++ gst_bus_add_watch(gstctx->bus, bus_message, &gstctx); ++ ++ gstctx->appsrc = (GstAppSrc*) ++ gst_bin_get_by_name(GST_BIN(gstctx->pipeline), "src"); ++ if (!gstctx->appsrc) ++ return -1; ++ ++ caps = gst_caps_new_simple("video/x-raw", ++ "format", G_TYPE_STRING, "BGRx", ++ "width", G_TYPE_INT, settings->width, ++ "height", G_TYPE_INT, settings->height, ++ NULL); ++ if (!caps) ++ return -1; ++ ++ g_object_set(G_OBJECT(gstctx->appsrc), ++ "caps", caps, ++ "stream-type", 0, ++ "format", GST_FORMAT_TIME, ++ "is-live", TRUE, ++ NULL); ++ gst_caps_unref(caps); ++ ++ gst_element_set_state((GstElement*)((void*)gstctx->pipeline), GST_STATE_PLAYING); ++ output->renderer->ctx = gstctx; ++ ++ return 0; ++} ++ ++static int ++recorder_enable(struct weston_transmitter_output *output) ++{ ++ struct gst_settings *settings; ++ ++ struct weston_output* base = &output->base; ++ struct weston_compositor *compositor = base->compositor; ++ struct weston_transmitter_remote* remote = output->remote; ++ ++ /* ++ * Limitation: ++ * Hard coding bitrate and crop params. ++ * In case of gst-recorder case these were taken from weston.ini ++ */ ++ int32_t bitrate = 3000000; ++ ++ settings = malloc(sizeof(* settings)); ++ settings->ip = remote->addr; ++ ++ settings->port = atoi(remote->port); ++ ++ settings->bitrate = bitrate; ++ settings->width = output->renderer->surface_width; ++ settings->height = output->renderer->surface_height; ++ ++ weston_log("gst-setting are :-->\n"); ++ weston_log("ip = %s \n",settings->ip); ++ weston_log("port = %d \n",settings->port); ++ weston_log("bitrate = %d \n",settings->bitrate); ++ weston_log("width = %d \n",settings->width); ++ weston_log("width = %d \n",settings->height); ++ ++ gst_pipe_init(output, settings); ++ ++ return 0; ++err: ++ weston_log("[gst recorder] %s:" ++ " invalid settings\n", ++ output->base.name); ++ free(settings); ++ return -1; ++} ++ ++static void waltham_renderer_repaint_output(struct weston_transmitter_output *output) ++{ ++ GstBuffer *gstbuffer; ++ GstMemory *mem; ++ GstAllocator *allocator; ++ int stride = output->renderer->surface_width * 4; ++ gsize offset = 0; ++ ++ if(!output->renderer->recorder_enabled) ++ { ++ recorder_enable(&output->base); ++ output->renderer->recorder_enabled = 1; ++ } ++ ++ gstbuffer = gst_buffer_new(); ++ allocator = gst_dmabuf_allocator_new(); ++ mem = gst_dmabuf_allocator_alloc(allocator, output->renderer->dmafd, ++ stride * output->renderer->surface_height); ++ gst_buffer_append_memory(gstbuffer, mem); ++ gst_buffer_add_video_meta_full(gstbuffer, ++ GST_VIDEO_FRAME_FLAG_NONE, ++ GST_VIDEO_FORMAT_BGRx, ++ output->renderer->surface_width, ++ output->renderer->surface_height, ++ 1, ++ &offset, ++ &stride); ++ ++ gst_app_src_push_buffer(output->renderer->ctx->appsrc, gstbuffer); ++ gst_object_unref(allocator); ++} ++ ++static int ++waltham_renderer_display_create(struct weston_transmitter_output *output) ++{ ++ struct waltham_renderer *wth_renderer; ++ ++ wth_renderer = zalloc(sizeof *wth_renderer); ++ if (wth_renderer == NULL) ++ return -1; ++ wth_renderer->base.repaint_output = waltham_renderer_repaint_output; ++ ++ output->renderer = &wth_renderer->base; ++ ++ return 0; ++} ++ ++WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = { ++ .display_create = waltham_renderer_display_create ++}; +diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.h b/waltham-transmitter/waltham-renderer/waltham-renderer.h +new file mode 100644 +index 0000000..a9ac513 +--- /dev/null ++++ b/waltham-transmitter/waltham-renderer/waltham-renderer.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial ++ * portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef TRANSMITTER_WALTHAM_RENDERER_H_ ++#define TRANSMITTER_WALTHAM_RENDERER_H_ ++ ++struct waltham_renderer_interface { ++ int (*display_create)(struct weston_transmitter_output *output); ++}; ++ ++struct gst_settings { ++ int width; ++ int height; ++ int bitrate; ++ char *ip; ++ int port; ++}; ++ ++#endif /* TRANSMITTER_WALTHAM_RENDERER_H_ */ +-- +2.7.4 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb new file mode 100644 index 000000000..55d3aee73 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb @@ -0,0 +1,25 @@ +DESCRIPTION = "Waltham is a network IPC library designed to resemble Wayland both protocol and protocol-API wise" +HOMEPAGE = "https://github.com/waltham/waltham" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://waltham-transmitter/COPYING;md5=d79ee9e66bb0f95d3386a7acae780b70" + +SRCREV = "${AUTOREV}" +SRC_URI = "https://gerrit.automotivelinux.org/gerrit/p/src/weston-ivi-plugins.git \ + file://0001-waltham-transmitter-initial-commit-of-waltham-transm.patch \ + " + +S = "${WORKDIR}/git" + +SRC_URI[md5sum] = "1819db75d41e607beb5520fafc3f542a" +SRC_URI[sha256sum] = "364f377f065d89ba44fd7efa10eec5cdb5108b892aaee5271c145ba10101b4c0" + +inherit autotools pkgconfig +inherit cmake + +DEPENDS += "libdrm virtual/kernel wayland waltham weston gstreamer1.0 gstreamer" + +FILES_${PN} += "*" + +FILES_${PN}-dbg += "${libdir}/weston/.dbg/*" +FILES_${PN}-dbg += "{libdir}/libweston-2/.dbg/*" \ No newline at end of file diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-ivi-shell-register-ivi_layout_interface.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-ivi-shell-register-ivi_layout_interface.patch new file mode 100644 index 000000000..87d883c02 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-ivi-shell-register-ivi_layout_interface.patch @@ -0,0 +1,91 @@ +From 5b1d282c7a7d2badf74bb19f9ddc0d49d3d4562b Mon Sep 17 00:00:00 2001 +From: Emre Ucan +Date: Thu, 25 Jan 2018 14:36:10 +0100 +Subject: [PATCH] ivi-shell: register ivi_layout_interface + +Signed-off-by: Emre Ucan +Reviewed-by: Pekka Paalanen +--- + ivi-shell/ivi-layout-export.h | 13 +++++++++++++ + ivi-shell/ivi-layout.c | 6 ++++++ + ivi-shell/ivi-shell.c | 2 -- + 3 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h +index 2317d6e..9452691 100644 +--- a/ivi-shell/ivi-layout-export.h ++++ b/ivi-shell/ivi-layout-export.h +@@ -59,6 +59,7 @@ extern "C" { + + #include "stdbool.h" + #include "compositor.h" ++#include "plugin-registry.h" + + #define IVI_SUCCEEDED (0) + #define IVI_FAILED (-1) +@@ -140,6 +141,8 @@ enum ivi_layout_transition_type{ + IVI_LAYOUT_TRANSITION_MAX, + }; + ++#define IVI_LAYOUT_API_NAME "ivi_layout_api_v1" ++ + struct ivi_layout_interface { + + /** +@@ -580,6 +583,16 @@ struct ivi_layout_interface { + (*get_surface)(struct weston_surface *surface); + }; + ++static inline const struct ivi_layout_interface * ++ivi_layout_get_api(struct weston_compositor *compositor) ++{ ++ const void *api; ++ api = weston_plugin_api_get(compositor, IVI_LAYOUT_API_NAME, ++ sizeof(struct ivi_layout_interface)); ++ ++ return (const struct ivi_layout_interface *)api; ++} ++ + #ifdef __cplusplus + } + #endif /* __cplusplus */ +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index 64e4ead..c2c1a35 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -2000,6 +2000,8 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, + return ivisurf; + } + ++static struct ivi_layout_interface ivi_layout_interface; ++ + void + ivi_layout_init_with_compositor(struct weston_compositor *ec) + { +@@ -2028,6 +2030,10 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec) + + layout->transitions = ivi_layout_transition_set_create(ec); + wl_list_init(&layout->pending_transition_list); ++ ++ weston_plugin_api_register(ec, IVI_LAYOUT_API_NAME, ++ &ivi_layout_interface, ++ sizeof(struct ivi_layout_interface)); + } + + static struct ivi_layout_interface ivi_layout_interface = { +diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c +index 67619b8..2dabdf9 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -425,8 +425,6 @@ ivi_shell_setting_create(struct ivi_shell_setting *dest, + if (!dest->ivi_module && + weston_config_section_get_string(section, "ivi-module", + &dest->ivi_module, NULL) < 0) { +- weston_log("Error: ivi-shell: No ivi-module set\n"); +- result = -1; + } + + weston_config_section_get_bool(section, "developermode", +-- +2.7.4 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-transmitter-add-an-incomplete-plugin-output-and-poin.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-transmitter-add-an-incomplete-plugin-output-and-poin.patch deleted file mode 100644 index bf2f05ef1..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0017-transmitter-add-an-incomplete-plugin-output-and-poin.patch +++ /dev/null @@ -1,2154 +0,0 @@ -From aa3ea1af1dfa0e0ef5b452d8a5c53cd3eb508f52 Mon Sep 17 00:00:00 2001 -From: Pekka Paalanen -Date: Wed, 2 Mar 2016 16:57:45 +0200 -Subject: [PATCH 1/3] transmitter: add an incomplete plugin (output and - pointer) - -Enabled with ./configure --enable-surface-remoting - -Draft the public API for binding and unbinding a surface for remoting, -and another for ivi-shell specifics. - -Add the plumbing needed to relay a configure event from the network to -the shell, to be forwarded to the application. - -Implement support for (fake) connection object tracking. - -Create a weston_output for a (fake) remote output. Force the -sync-to-output on remoted surfaces. Use timers to fake wl_surface.enter -and frame callback events. Also Presentation feedback is poorly faked. - -Hooking to weston_surface happens in two ways: surface_configure in -Transmitter plugin API is used to relay the dx,dy from -wl_surface.attach, and weston_surface::apply_state_signal relays state -updates. - -Create a fake seat with pointer: - -- Add an internal pointer API that will be called by the networking code - for incoming input events. The API should match 1:1 to the events. - These functions will reimplement the parts of src/input.c to send out - the events to Wayland clients. - -- Implement pointer enter/leave of the internal pointer API. Code is - mimicked from weston_pointer_set_focus(), but without all the logic - needed to determine the right actions. - -- Implement pointer frame of the internal pointer API. - -- Add a fake pointer input generator. It only make the pointer enter the - surface remoted the most recently, and moves the pointer in a circle. - -All ways of getting pointer focus should be covered. Serial tracking is -the same as in Weston core. Seat maintains the pointer focus surface. -Focus_client is managed while Weston core never sees any focus. -Transmitter surface gained a destroy signal. - -Surface destruction relies on forwarding the destroy to the remote, -which will then reply with appropriate pointer.leave events. This is not -implemented by the input faking code. - -Transmitter is expected to open all inputs available on the remote and -multiplex those to local clients as clients subscribe. - -Notes about the design and guidelines for finishing the implementation -are included, and all the mockup code is annotated as "fake" so it is -easy to spot and replace with a proper network implementation. - -There are listener-based APIs for getting both remote connection status -changes, and per-surface stream status changes. - -Signed-off-by: Pekka Paalanen ---- - Makefile.am | 19 ++ - configure.ac | 9 + - transmitter/README | 53 ++++ - transmitter/input.c | 597 +++++++++++++++++++++++++++++++++++++++ - transmitter/output.c | 234 ++++++++++++++++ - transmitter/plugin.c | 638 ++++++++++++++++++++++++++++++++++++++++++ - transmitter/plugin.h | 207 ++++++++++++++ - transmitter/transmitter_api.h | 253 +++++++++++++++++ - 8 files changed, 2010 insertions(+) - create mode 100644 transmitter/README - create mode 100644 transmitter/input.c - create mode 100644 transmitter/output.c - create mode 100644 transmitter/plugin.c - create mode 100644 transmitter/plugin.h - create mode 100644 transmitter/transmitter_api.h - -diff --git a/Makefile.am b/Makefile.am -index cdf82ab..6cca875 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -502,6 +502,25 @@ cms_colord_la_SOURCES = \ - endif - endif - -+if ENABLE_SURFACE_REMOTING -+module_LTLIBRARIES += transmitter.la -+transmitter_la_LDFLAGS = -module -avoid-version -+transmitter_la_CFLAGS = \ -+ $(COMPOSITOR_CFLAGS) \ -+ $(AM_CFLAGS) -+transmitter_la_LIBADD = $(COMPOSITOR_LIBS) -+transmitter_la_SOURCES = \ -+ transmitter/plugin.c \ -+ transmitter/plugin.h \ -+ transmitter/output.c \ -+ transmitter/input.c \ -+ transmitter/transmitter_api.h \ -+ shared/helpers.h \ -+ shared/timespec-util.h \ -+ shared/zalloc.h \ -+ src/compositor.h -+endif -+ - noinst_PROGRAMS += spring-tool - spring_tool_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) - spring_tool_LDADD = $(COMPOSITOR_LIBS) -lm -diff --git a/configure.ac b/configure.ac -index d0dee1b..06cda73 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -562,6 +562,14 @@ AS_IF([test "x$have_systemd_login_209" = "xyes"], - [AC_DEFINE([HAVE_SYSTEMD_LOGIN_209], [1], [Have systemd-login >= 209])]) - - -+# surface remoting -+AC_ARG_ENABLE(surface-remoting, -+ AS_HELP_STRING([--enable-surface-remoting], -+ [support for surface remoting over network]),, -+ enable_surface_remoting=no) -+AM_CONDITIONAL(ENABLE_SURFACE_REMOTING, test "x$enable_surface_remoting" = "xyes") -+ -+ - # Note that other features might want libxml2, or this feature might use - # alternative xml libraries at some point. Therefore the feature and - # pre-requisite concepts are split. -@@ -750,4 +758,5 @@ AC_MSG_RESULT([ - libunwind Support ${have_libunwind} - VA H.264 encoding Support ${have_libva} - GStreamer H.264 enc. Support ${enable_gst_recorder} -+ Surface remoting support ${enable_surface_remoting} - ]) -diff --git a/transmitter/README b/transmitter/README -new file mode 100644 -index 0000000..a7977ba ---- /dev/null -+++ b/transmitter/README -@@ -0,0 +1,53 @@ -+Testing Transmitter with ivi-shell -+ -+The current implementation of Transmitter is a stub which interfaces to -+other Weston parts appropriately, but all networking is just a mockup. -+ -+ -+Configure Weston with --enable-surface-remoting to build the Transmitter -+plugin. -+ -+In weston.ini, add 'transmitter.so' to the 'modules' key under '[core]', and -+make sure the 'shell' is 'ivi-shell.so'. Follow the ivi-shell example -+weston.ini for everything else. -+ -+When you start weston, the log should contain something like this: -+ -+[13:13:54.799] Loading module '/home/pq/local/lib/weston/ivi-shell.so' -+[13:13:54.799] launching '/home/pq/local/libexec/weston-keyboard' -+[13:13:54.799] Loading module '/home/pq/local/lib/weston/hmi-controller.so' -+[13:13:54.799] Loading module '/home/pq/local/lib/weston/transmitter.so' -+[13:13:54.799] Registered plugin API 'transmitter_v1' of size 48 -+[13:13:54.799] Registered plugin API 'transmitter_ivi_v1' of size 16 -+[13:13:54.799] Transmitter initialized. -+[13:13:54.799] ivi-layout: Transmitter enabled. -+[13:13:54.799] launching '/home/pq/build/weston/weston-ivi-shell-user-interface' -+[13:13:54.799] hmi-controller: Transmitter enabled. -+[13:13:54.799] Transmitter connecting to 0.0.0.0:66... -+[13:13:55.800] Transmitter connected to 0.0.0.0:66. -+[13:13:55.800] hmi-controller: connection status 0 -+[13:13:55.800] Transmitter created output 'transmitter-0.0.0.0:66-1': Weston-Transmitter, transmitter-0.0.0.0:66-1, 0 -+[13:13:55.800] Transmitter created seat=0x1c37bd0 'transmitter-0.0.0.0:66-default' -+[13:13:55.800] Transmitter created pointer=0x1c38430 for seat 0x1c37bd0 -+[13:13:55.800] transmitter_start_repaint_loop(transmitter-0.0.0.0:66-1) -+ -+ -+If you have edited a client to have ivi-id >= 0xfaa01000, when you start that -+client it should be "remoted" automatically and not appear on screen. -+ -+You can also manually start remoting: -+- Start an IVI application. -+- Move pointer onto the application window. -+- Press Mod+Shift+space, and then 'k'. -+- The window should disappear. -+ -+Weston log will indicate remoting has started: -+ -+[13:18:24.572] HMI transmitting surface 0x1c3dad0, ivi-id 0x9ff6 -+[13:18:24.572] Transmitter: update surface 0x1c3dad0 (0, 0), 0 cb -+[13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6) -+[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 -+ -+Once remoting has started, the mockup code will generate fake pointer input for -+the window. This can be seen with e.g. weston-eventdemo, or running an -+application with WAYLAND_DEBUG=client. -diff --git a/transmitter/input.c b/transmitter/input.c -new file mode 100644 -index 0000000..0ba04d4 ---- /dev/null -+++ b/transmitter/input.c -@@ -0,0 +1,597 @@ -+/* -+ * Copyright (C) 2016 DENSO CORPORATION -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+ -+/* for fake stuff */ -+#include -+ -+#include "compositor.h" -+#include "helpers.h" -+ -+#include "plugin.h" -+#include "transmitter_api.h" -+ -+/** @file -+ * -+ * This is an implementation of a remote input. -+ * -+ * Request wl_data_device_manager.get_data_device would need to be blocked, -+ * except maybe it's not necessary, we just "forget" to forward data to/from -+ * the remote wl_seat. It might still work inside the local compositor. -+ * -+ * weston_compositor_set_default_pointer_grab() will break our pointer -+ * implementation, but no in-tree code is calling it. -+ */ -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+static void -+pointer_focus_grab_handler(struct weston_pointer_grab *grab) -+{ -+ /* No-op: -+ * -+ * Weston internal events do not change the focus. -+ */ -+} -+ -+static void -+pointer_motion_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ struct weston_pointer_motion_event *event) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_button_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_axis_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ struct weston_pointer_axis_event *event) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_axis_source_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t source) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_frame_grab_handler(struct weston_pointer_grab *grab) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_cancel_grab_handler(struct weston_pointer_grab *grab) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+/* These handlers would be called from the notify_*() functions in src/input.c. -+ * However, as we do not use the low level input notify_*() functions that -+ * backends drive, these are mostly uncalled, except the focus handler which -+ * weston core generates internally. -+ */ -+static const struct weston_pointer_grab_interface pointer_grab_impl = { -+ pointer_focus_grab_handler, -+ pointer_motion_grab_handler, -+ pointer_button_grab_handler, -+ pointer_axis_grab_handler, -+ pointer_axis_source_grab_handler, -+ pointer_frame_grab_handler, -+ pointer_cancel_grab_handler, -+}; -+ -+/* The different ways to get pointer focus on a remoted surface: -+ * -+ * 1. Transmitter seat has pointer. The client has wl_pointer. Transmitter -+ * receives pointer.enter. (transmitter_seat_pointer_enter()) -+ * -+ * 2. Transmitter seat has pointer. Transmitter has received pointer.enter. -+ * The client calls wl_seat.get_pointer. => send enter only on the new -+ * wl_pointer. (seat_get_pointer_handler()) -+ * -+ * 3. Client has wl_pointer. Transmitter seat adds pointer capability. -+ * Transmitter receives pointer.enter. wl_pointer MUST NOT enter, -+ * specified by wl_seat.capabilities. -+ * -+ * By definition, Transmitter cannot receive pointer.enter without having -+ * pointer capability in the seat, so no other combinations are possible. -+ * -+ * The same applies to wl_keyboard and wl_touch. -+ */ -+ -+/* Implementor notes: -+ * -+ * The handling of all of wl_pointer, wl_keyboard and wl_touch should be -+ * similar. To make it work, we need to add a signal to each of the -+ * wl_seat.get_pointer, wl_seat.get_keyboard, and wl_seat.get_touch request -+ * handlers in Weston core. Otherwise we cannot implement the case 2 of gaining -+ * input device focus. -+ * -+ * However, weston_keyboard::focus is a weston_surface, not a weston_view, so -+ * we may be able to leverage more of the core implementation and maybe do -+ * without the wl_seat.get_keyboard signal. Weston_touch uses a weston_view, so -+ * that is similar to weston_pointer. -+ * -+ * It might be useful to convert weston_keyboard and weston_touch to use a -+ * similar thing as weston_pointer_client, in case it makes things more -+ * consistent. It might also fix issues when a client has multiple copies of a -+ * wl_keyboard or a wl_touch, but that is getting off-topic. -+ * -+ * This file shows which part of the Weston input path we skip and where we -+ * hook in. We skip everything starting from the notify_*() API used by -+ * backends, and stub out the grab handlers. Instead of actual grab handlers, -+ * we have our own network protocol events handlers. They do much of the same -+ * as normal grab handlers would do, except focus is pre-given, and we do not -+ * have weston_view for the focus surfaces, so we need to bypass core code -+ * dealing with those. -+ * -+ * Our remote seat implementation will leave many struct members unused and -+ * replicate some from weston_pointer, weston_keyboard, and weston_touch. -+ * Weston core must be kept out from the focus handling business, because we -+ * will send enter/leave events ourselves, and focus assignments are given -+ * to us from the remote, they cannot be changed at will by the local Weston. -+ */ -+ -+/** Callback from the protocol request handler for wl_seat.get_pointer -+ * -+ * The Weston core handler never sees focus set on the weston_pointer, -+ * so it won't send wl_pointer.enter nor set focus_client. It does call -+ * weston_pointer_ensure_pointer_client() though. -+ */ -+static void -+seat_get_pointer_handler(struct wl_listener *listener, void *data) -+{ -+ struct wl_resource *new_pointer = data; -+ struct weston_transmitter_seat *seat; -+ struct wl_resource *surface; -+ struct weston_pointer_client *pointer_client; -+ struct wl_client *client; -+ struct weston_pointer *pointer; -+ -+ seat = wl_container_of(listener, seat, get_pointer_listener); -+ if (!seat->pointer_focus) -+ return; -+ -+ client = wl_resource_get_client(new_pointer); -+ surface = seat->pointer_focus->surface->resource; -+ -+ if (wl_resource_get_client(surface) != client) -+ return; -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ assert(pointer); /* guaranteed by having pointer_focus */ -+ pointer_client = weston_pointer_get_pointer_client(pointer, client); -+ -+ if (!pointer->focus_client) -+ pointer->focus_client = pointer_client; -+ else -+ assert(pointer->focus_client == pointer_client); -+ -+ wl_pointer_send_enter(new_pointer, pointer->focus_serial, surface, -+ seat->pointer_surface_x, seat->pointer_surface_y); -+ -+ if (wl_resource_get_version(new_pointer) >= -+ WL_POINTER_FRAME_SINCE_VERSION) -+ wl_pointer_send_frame(new_pointer); -+} -+ -+static void -+transmitter_seat_create_pointer(struct weston_transmitter_seat *seat) -+{ -+ struct weston_pointer *pointer; -+ -+ seat->pointer_phase = 0.0; -+ seat->pointer_surface_x = wl_fixed_from_int(-1000000); -+ seat->pointer_surface_y = wl_fixed_from_int(-1000000); -+ seat->pointer_focus = NULL; -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ weston_seat_init_pointer(&seat->base); -+ -+ seat->get_pointer_listener.notify = seat_get_pointer_handler; -+ wl_signal_add(&seat->base.get_pointer_signal, -+ &seat->get_pointer_listener); -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ -+ /* not exported: -+ * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */ -+ pointer->default_grab.interface = &pointer_grab_impl; -+ -+ /* Changes to local outputs are irrelevant. */ -+ wl_list_remove(&pointer->output_destroy_listener.link); -+ wl_list_init(&pointer->output_destroy_listener.link); -+ -+ weston_log("Transmitter created pointer=%p for seat %p\n", -+ pointer, &seat->base); -+} -+ -+static void -+seat_pointer_focus_destroy_handler(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs = data; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(listener, seat, pointer_focus_destroy_listener); -+ assert(seat->pointer_focus == txs); -+ -+ seat->pointer_focus = NULL; -+} -+ -+void -+transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y) -+{ -+ struct wl_client *client; -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ assert(pointer); -+ -+ assert(txs->surface); -+ client = wl_resource_get_client(txs->surface->resource); -+ -+ seat->pointer_focus = txs; -+ seat->pointer_focus_destroy_listener.notify = -+ seat_pointer_focus_destroy_handler; -+ wl_signal_add(&txs->destroy_signal, -+ &seat->pointer_focus_destroy_listener); -+ -+ /* If pointer-focus gets destroyed, txs will get destroyed, the -+ * remote surface object is destroyed, and the remote will send a -+ * leave and a frame. -+ */ -+ -+ seat->pointer_surface_x = surface_x; -+ seat->pointer_surface_y = surface_y; -+ -+ pointer->focus_client = weston_pointer_get_pointer_client(pointer, -+ client); -+ pointer->focus_serial = serial; -+ -+ /* pointer->focus is not used, because it is a weston_view, while -+ * remoted surfaces have no views. -+ * -+ * pointer->x,y are not used because they are in global coordinates. -+ * Remoted surfaces are not in the global space at all, so there are -+ * no such coordinates. -+ */ -+ -+ if (!pointer->focus_client) -+ return; -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_enter(resource, -+ serial, -+ txs->surface->resource, -+ surface_x, surface_y); -+ } -+} -+ -+void -+transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *surface_resource; -+ struct wl_resource *resource; -+ -+ if (txs != seat->pointer_focus) { -+ weston_log("Transmitter Warning: pointer leave for %p, expected %p\n", -+ txs, seat->pointer_focus); -+ } -+ -+ seat->pointer_focus = NULL; -+ wl_list_remove(&seat->pointer_focus_destroy_listener.link); -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ if (!txs) -+ return; -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ assert(pointer); -+ if (!pointer->focus_client) -+ return; -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) -+ wl_pointer_send_leave(resource, serial, surface_resource); -+ -+ /* Do not reset pointer->focus_client, because we need to be able -+ * to send a following 'frame' event in -+ * transmitter_seat_pointer_frame(). -+ */ -+} -+ -+void -+transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ assert(pointer); -+ -+ seat->pointer_surface_x = surface_x; -+ seat->pointer_surface_y = surface_y; -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_motion(resource, time, -+ surface_x, surface_y); -+ } -+} -+ -+void -+transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ assert(!"TODO"); -+} -+ -+void -+transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis, -+ wl_fixed_t value) -+{ -+ assert(!"TODO"); -+} -+ -+void -+transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat) -+{ -+ struct weston_pointer *pointer; -+ -+ pointer = weston_seat_get_pointer(&seat->base); -+ if (pointer) -+ weston_pointer_send_frame(pointer); -+} -+ -+void -+transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, -+ uint32_t axis_source) -+{ -+ assert(!"TODO"); -+} -+ -+void -+transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis) -+{ -+ assert(!"TODO"); -+} -+ -+void -+transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, -+ uint32_t axis, -+ int32_t discrete) -+{ -+ assert(!"TODO"); -+} -+ -+static char * -+make_seat_name(struct weston_transmitter_remote *remote, const char *name) -+{ -+ char *str; -+ -+ if (asprintf(&str, "transmitter-%s-%s", remote->addr, name) < 0) -+ return NULL; -+ -+ return str; -+} -+ -+void -+transmitter_seat_destroy(struct weston_transmitter_seat *seat) -+{ -+ wl_list_remove(&seat->link); -+ -+ weston_log("Transmitter destroy seat=%p\n", &seat->base); -+ -+ weston_seat_release(&seat->base); -+ -+ wl_list_remove(&seat->get_pointer_listener.link); -+ wl_list_remove(&seat->pointer_focus_destroy_listener.link); -+ -+ if (seat->pointer_timer) -+ wl_event_source_remove(seat->pointer_timer); -+ -+ free(seat); -+} -+ -+int -+transmitter_remote_create_seat(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_seat *seat = NULL; -+ char *name = NULL; -+ -+ seat = zalloc(sizeof *seat); -+ if (!seat) -+ goto fail; -+ -+ wl_list_init(&seat->get_pointer_listener.link); -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ /* XXX: get the name from remote */ -+ name = make_seat_name(remote, "default"); -+ if (!name) -+ goto fail; -+ -+ weston_seat_init(&seat->base, remote->transmitter->compositor, name); -+ free(name); -+ -+ /* Hide the weston_seat from the rest of Weston, there are too many -+ * things making assumptions: -+ * - backends assume they control all seats -+ * - shells assume they control all input foci -+ * We do not want either to mess with our seat. -+ */ -+ wl_list_remove(&seat->base.link); -+ wl_list_init(&seat->base.link); -+ -+ /* The weston_compositor::seat_created_signal has already been -+ * emitted. Shells use it to subscribe to focus changes, but we should -+ * never handle focus with weston core... except maybe with keyboard. -+ * text-backend.c will also act on the new seat. -+ * It is possible weston_seat_init() needs to be split to fix this -+ * properly. -+ */ -+ -+ weston_log("Transmitter created seat=%p '%s'\n", -+ &seat->base, seat->base.seat_name); -+ -+ /* XXX: mirror remote capabilities */ -+ transmitter_seat_create_pointer(seat); -+ -+ wl_list_insert(&remote->seat_list, &seat->link); -+ -+ return 0; -+ -+fail: -+ free(seat); -+ free(name); -+ -+ return -1; -+} -+ -+static void -+fake_pointer_get_position(struct weston_transmitter_seat *seat, double step, -+ wl_fixed_t *x, wl_fixed_t *y) -+{ -+ double s, c; -+ -+ seat->pointer_phase += step; -+ while (seat->pointer_phase > 2.0 * M_PI) -+ seat->pointer_phase -= 2.0 * M_PI; -+ -+ sincos(seat->pointer_phase, &s, &c); -+ *x = wl_fixed_from_double(100.0 + 50.0 * c); -+ *y = wl_fixed_from_double(100.0 + 50.0 * s); -+} -+ -+static int -+fake_pointer_timer_handler(void *data) -+{ -+ struct weston_transmitter_seat *seat = data; -+ wl_fixed_t x, y; -+ uint32_t time; -+ -+ time = weston_compositor_get_time(); -+ -+ fake_pointer_get_position(seat, 18.0 / 180.0 * M_PI, &x, &y); -+ transmitter_seat_pointer_motion(seat, time, x, y); -+ transmitter_seat_pointer_frame(seat); -+ -+ wl_event_source_timer_update(seat->pointer_timer, 100); -+ -+ return 0; -+} -+ -+int -+transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, -+ struct weston_transmitter_surface *txs) -+{ -+ struct wl_event_loop *loop; -+ wl_fixed_t x, y; -+ uint32_t serial = 5; -+ -+ /* remove focus from earlier surface */ -+ transmitter_seat_pointer_leave(seat, serial++, seat->pointer_focus); -+ transmitter_seat_pointer_frame(seat); -+ -+ /* set pointer focus to surface */ -+ fake_pointer_get_position(seat, 0.0, &x, &y); -+ transmitter_seat_pointer_enter(seat, serial++, txs, x, y); -+ transmitter_seat_pointer_frame(seat); -+ -+ if (!seat->pointer_timer) { -+ /* schedule timer for motion */ -+ loop = wl_display_get_event_loop(seat->base.compositor->wl_display); -+ seat->pointer_timer = wl_event_loop_add_timer(loop, -+ fake_pointer_timer_handler, seat); -+ wl_event_source_timer_update(seat->pointer_timer, 100); -+ } -+ -+ /* XXX: if the now focused surface disappears, we should call -+ * transmitter_seat_pointer_leave() as part of the mockup. Otherwise -+ * you get a "Transmitter Warning: no pointer->focus_client?". -+ */ -+ -+ return 0; -+} -diff --git a/transmitter/output.c b/transmitter/output.c -new file mode 100644 -index 0000000..6a78721 ---- /dev/null -+++ b/transmitter/output.c -@@ -0,0 +1,234 @@ -+/* -+ * Copyright (C) 2016 DENSO CORPORATION -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+ -+#include "compositor.h" -+#include "helpers.h" -+ -+#include "plugin.h" -+#include "transmitter_api.h" -+ -+/** @file -+ * -+ * This is an implementation of a remote output. -+ * -+ * A remote output must not be accepted as an argument to: -+ * - wl_shell_surface.set_fullscreen -+ * - wl_shell_surface.set_maximized -+ * - zwp_fullscreen_shell_v1.present_surface -+ * - zwp_fullscreen_shell_v1.present_surface_for_mode -+ * - zwp_input_panel_surface_v1.set_toplevel -+ * - xdg_surface.set_fullscreen -+ * -+ * If a remote output is an argument to the above or similar requests, -+ * it should have the same effect as NULL if possible. -+ * -+ * @todo Should we instead accept the argument and have it start remoting -+ * automatically? That would be shell-specific. -+ * -+ * In ivi-shell's case, only zwp_input_panel_surface_v1.set_toplevel is -+ * reachable from keyboard.c. That just blindly uses whatever the first -+ * output happens to be, so there is no need to check for now. -+ * -+ * @todo Add weston_output_set_remote() which sets weston_output::is_remote -+ * to true and inits weston_output::link. This should be made mutually -+ * exclusive with weston_compositor_add_output(). -+ */ -+ -+static inline struct weston_transmitter_output * -+to_transmitter_output(struct weston_output *base) -+{ -+ return container_of(base, struct weston_transmitter_output, base); -+} -+ -+static char * -+make_model(struct weston_transmitter_remote *remote, int name) -+{ -+ char *str; -+ -+ if (asprintf(&str, "transmitter-%s-%d", remote->addr, name) < 0) -+ return NULL; -+ -+ return str; -+} -+ -+static int -+make_mode_list(struct wl_list *list, -+ const struct weston_transmitter_output_info *info) -+{ -+ struct weston_mode *mode; -+ -+ mode = zalloc(sizeof *mode); -+ if (!mode) -+ return -1; -+ -+ *mode = info->mode; -+ wl_list_insert(list->prev, &mode->link); -+ -+ return 0; -+} -+ -+static struct weston_mode * -+get_current_mode(struct wl_list *mode_list) -+{ -+ struct weston_mode *mode; -+ -+ wl_list_for_each(mode, mode_list, link) -+ if (mode->flags & WL_OUTPUT_MODE_CURRENT) -+ return mode; -+ -+ assert(0); -+ return NULL; -+} -+ -+static void -+free_mode_list(struct wl_list *mode_list) -+{ -+ struct weston_mode *mode; -+ -+ while (!wl_list_empty(mode_list)) { -+ mode = container_of(mode_list->next, struct weston_mode, link); -+ -+ wl_list_remove(&mode->link); -+ free(mode); -+ } -+} -+ -+void -+transmitter_output_destroy(struct weston_transmitter_output *output) -+{ -+ weston_log("Transmitter destroying output '%s'\n", output->base.name); -+ -+ wl_list_remove(&output->link); -+ -+ free_mode_list(&output->base.mode_list); -+ free(output->base.serial_number); -+ free(output->base.model); -+ free(output->base.make); -+ -+ weston_output_destroy(&output->base); -+ free(output); -+} -+ -+static void -+transmitter_output_destroy_(struct weston_output *base) -+{ -+ struct weston_transmitter_output *output = to_transmitter_output(base); -+ -+ transmitter_output_destroy(output); -+} -+ -+static void -+transmitter_start_repaint_loop(struct weston_output *base) -+{ -+ weston_log("%s(%s)\n", __func__, base->name); -+} -+ -+static int -+transmitter_output_repaint(struct weston_output *base, -+ pixman_region32_t *damage) -+{ -+ weston_log("%s(%s)\n", __func__, base->name); -+ -+ return -1; -+} -+ -+int -+transmitter_remote_create_output( -+ struct weston_transmitter_remote *remote, -+ const struct weston_transmitter_output_info *info) -+{ -+ struct weston_transmitter_output *output; -+ -+ output = zalloc(sizeof *output); -+ if (!output) -+ return -1; -+ -+ output->base.subpixel = info->subpixel; -+ -+ output->base.name = make_model(remote, 1); -+ output->base.make = strdup(WESTON_TRANSMITTER_OUTPUT_MAKE); -+ output->base.model = make_model(remote, 1); -+ output->base.serial_number = strdup("0"); -+ -+ wl_list_init(&output->base.mode_list); -+ if (make_mode_list(&output->base.mode_list, info) < 0) -+ goto fail; -+ -+ output->base.current_mode = get_current_mode(&output->base.mode_list); -+ /* WL_OUTPUT_MODE_CURRENT already set */ -+ -+ weston_output_init(&output->base, remote->transmitter->compositor); -+ -+ /* -+ * renderer_output_create skipped: -+ * no renderer awareness is needed for this output -+ */ -+ -+ /* -+ * weston_compositor_add_output() skipped: -+ * Most other code uses weston_compositor::output_list when traversing -+ * all outputs, we do not want any of that. -+ * Also weston_compositor::output_created_signal must not trigger -+ * for this output, since we must not involve input device management -+ * or color management or any kind of local management. -+ */ -+ -+ output->base.start_repaint_loop = transmitter_start_repaint_loop; -+ output->base.repaint = transmitter_output_repaint; -+ output->base.destroy = transmitter_output_destroy_; -+ output->base.assign_planes = NULL; -+ output->base.set_dpms = NULL; -+ output->base.switch_mode = NULL; -+ output->base.gamma_size = 0; -+ output->base.set_gamma = NULL; -+ -+ output->base.native_mode = output->base.current_mode; -+ output->base.native_scale = output->base.current_scale; -+ -+ output->remote = remote; -+ wl_list_insert(&remote->output_list, &output->link); -+ -+ weston_log("Transmitter created output '%s': %s, %s, %s\n", -+ output->base.name, output->base.make, output->base.model, -+ output->base.serial_number); -+ -+ return 0; -+ -+fail: -+ free_mode_list(&output->base.mode_list); -+ free(output->base.serial_number); -+ free(output->base.model); -+ free(output->base.make); -+ free(output->base.name); -+ free(output); -+ -+ return -1; -+} -diff --git a/transmitter/plugin.c b/transmitter/plugin.c -new file mode 100644 -index 0000000..c5e56d3 ---- /dev/null -+++ b/transmitter/plugin.c -@@ -0,0 +1,638 @@ -+/* -+ * Copyright (C) 2016 DENSO CORPORATION -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "compositor.h" -+#include "helpers.h" -+#include "timespec-util.h" -+ -+#include "plugin.h" -+#include "transmitter_api.h" -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+/** Send configure event through ivi-shell. -+ * -+ * \param txs The Transmitter surface. -+ * \param width Suggestion for surface width. -+ * \param height Suggestion for surface height. -+ * -+ * When the networking code receives a ivi_surface.configure event, it calls -+ * this function to relay it to the application. -+ * -+ * \c txs cannot be a zombie, because transmitter_surface_zombify() must -+ * tear down the network link, so a zombie cannot receive events. -+ */ -+void -+transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, -+ int32_t width, int32_t height) -+{ -+ assert(txs->resize_handler); -+ if (!txs->resize_handler) -+ return; -+ -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ -+ txs->resize_handler(txs->resize_handler_data, width, height); -+} -+ -+static int -+frame_callback_handler(void *data) /* fake */ -+{ -+ struct weston_transmitter_surface *txs = data; -+ struct weston_frame_callback *cb, *cnext; -+ struct weston_output *output; -+ struct weston_compositor *compositor; -+ uint32_t frame_time; -+ uint32_t presented_flags; -+ int32_t refresh_nsec; -+ struct timespec stamp; -+ -+ compositor = txs->remote->transmitter->compositor; -+ output = txs->sync_output; -+ -+ /* wl_surface.enter should arrive before any frame callbacks, -+ * but remote might send frame callbacks for non-visible too. -+ */ -+ if (!output) -+ return 0; -+ -+ /* XXX: eeeew */ -+ frame_time = weston_compositor_get_time(); -+ -+ wl_list_for_each_safe(cb, cnext, &txs->frame_callback_list, link) { -+ wl_callback_send_done(cb->resource, frame_time); -+ wl_resource_destroy(cb->resource); -+ } -+ -+ presented_flags = 0; -+ refresh_nsec = millihz_to_nsec(output->current_mode->refresh); -+ /* XXX: waaahhhahaa */ -+ weston_compositor_read_presentation_clock(compositor, &stamp); -+ weston_presentation_feedback_present_list(&txs->feedback_list, -+ output, refresh_nsec, &stamp, -+ output->msc, -+ presented_flags); -+ -+ return 0; -+} -+ -+static void -+fake_frame_callback(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter *txr = txs->remote->transmitter; -+ struct wl_event_loop *loop; -+ -+ if (!txs->frame_timer) { -+ loop = wl_display_get_event_loop(txr->compositor->wl_display); -+ txs->frame_timer = -+ wl_event_loop_add_timer(loop, -+ frame_callback_handler, txs); -+ } -+ -+ wl_event_source_timer_update(txs->frame_timer, 85); -+} -+ -+static void -+transmitter_surface_configure(struct weston_transmitter_surface *txs, -+ int32_t dx, int32_t dy) -+{ -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ -+ txs->attach_dx += dx; -+ txs->attach_dy += dy; -+} -+ -+static void -+transmitter_surface_gather_state(struct weston_transmitter_surface *txs) -+{ -+ weston_log("Transmitter: update surface %p (%d, %d), %d cb\n", -+ txs->surface, txs->attach_dx, txs->attach_dy, -+ wl_list_length(&txs->surface->frame_callback_list)); -+ -+ wl_list_insert_list(&txs->frame_callback_list, -+ &txs->surface->frame_callback_list); -+ wl_list_init(&txs->surface->frame_callback_list); -+ -+ wl_list_insert_list(&txs->feedback_list, &txs->surface->feedback_list); -+ wl_list_init(&txs->surface->feedback_list); -+ -+ /* TODO: transmit surface state to remote */ -+ -+ txs->attach_dx = 0; -+ txs->attach_dy = 0; -+} -+ -+/** weston_surface apply state signal handler */ -+static void -+transmitter_surface_apply_state(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs = -+ container_of(listener, struct weston_transmitter_surface, -+ apply_state_listener); -+ -+ assert(data == NULL); -+ -+ transmitter_surface_gather_state(txs); -+ fake_frame_callback(txs); -+} -+ -+/** Mark the weston_transmitter_surface dead. -+ * -+ * Stop all remoting actions on this surface. -+ * -+ * Still keeps the pointer stored by a shell valid, so it can be freed later. -+ */ -+static void -+transmitter_surface_zombify(struct weston_transmitter_surface *txs) -+{ -+ struct weston_frame_callback *framecb, *cnext; -+ -+ /* may be called multiple times */ -+ if (!txs->surface) -+ return; -+ -+ wl_signal_emit(&txs->destroy_signal, txs); -+ -+ wl_list_remove(&txs->surface_destroy_listener.link); -+ weston_log("Transmitter unbound surface %p.\n", txs->surface); -+ txs->surface = NULL; -+ -+ wl_list_remove(&txs->sync_output_destroy_listener.link); -+ wl_list_remove(&txs->apply_state_listener.link); -+ -+ if (txs->map_timer) -+ wl_event_source_remove(txs->map_timer); -+ if (txs->frame_timer) -+ wl_event_source_remove(txs->frame_timer); -+ -+ weston_presentation_feedback_discard_list(&txs->feedback_list); -+ wl_list_for_each_safe(framecb, cnext, &txs->frame_callback_list, link) -+ wl_resource_destroy(framecb->resource); -+ -+ /* In case called from destroy_transmitter() */ -+ txs->remote = NULL; -+} -+ -+static void -+transmitter_surface_destroy(struct weston_transmitter_surface *txs) -+{ -+ transmitter_surface_zombify(txs); -+ -+ wl_list_remove(&txs->link); -+ free(txs); -+} -+ -+/** weston_surface destroy signal handler */ -+static void -+transmitter_surface_destroyed(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs = -+ container_of(listener, struct weston_transmitter_surface, -+ surface_destroy_listener); -+ -+ assert(data == txs->surface); -+ -+ transmitter_surface_zombify(txs); -+} -+ -+static struct weston_transmitter_surface * -+transmitter_surface_get(struct weston_surface *ws) -+{ -+ struct wl_listener *listener; -+ struct weston_transmitter_surface *txs; -+ -+ listener = wl_signal_get(&ws->destroy_signal, -+ transmitter_surface_destroyed); -+ -+ if (!listener) -+ return NULL; -+ -+ txs = container_of(listener, struct weston_transmitter_surface, -+ surface_destroy_listener); -+ assert(ws == txs->surface); -+ -+ return txs; -+} -+ -+static void -+sync_output_destroy_handler(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs; -+ -+ txs = container_of(listener, struct weston_transmitter_surface, -+ sync_output_destroy_listener); -+ -+ wl_list_remove(&txs->sync_output_destroy_listener.link); -+ wl_list_init(&txs->sync_output_destroy_listener.link); -+ -+ weston_surface_force_output(txs->surface, NULL); -+} -+ -+static void -+fake_input(struct weston_transmitter_surface *txs) -+{ -+ struct wl_list *seat_list = &txs->remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ assert(wl_list_length(seat_list) == 1); -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_fake_pointer_input(seat, txs); -+} -+ -+/* fake receiving wl_surface.enter(output) */ -+static int -+map_timer_handler(void *data) -+{ -+ struct weston_transmitter_surface *txs = data; -+ struct weston_transmitter_output *output; -+ -+ assert(!wl_list_empty(&txs->remote->output_list)); -+ -+ output = container_of(txs->remote->output_list.next, -+ struct weston_transmitter_output, link); -+ -+ txs->sync_output = &output->base; -+ txs->sync_output_destroy_listener.notify = sync_output_destroy_handler; -+ wl_list_remove(&txs->sync_output_destroy_listener.link); -+ wl_signal_add(&txs->sync_output->destroy_signal, -+ &txs->sync_output_destroy_listener); -+ -+ weston_surface_force_output(txs->surface, txs->sync_output); -+ -+ weston_log("Transmitter: surface %p entered output %s\n", -+ txs->surface, txs->sync_output->name); -+ -+ fake_frame_callback(txs); -+ fake_input(txs); -+ -+ return 0; -+} -+ -+/* Fake a delay for the remote end to map the surface to an output */ -+static void -+fake_output_mapping(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter *txr = txs->remote->transmitter; -+ struct wl_event_loop *loop; -+ -+ loop = wl_display_get_event_loop(txr->compositor->wl_display); -+ txs->map_timer = wl_event_loop_add_timer(loop, map_timer_handler, txs); -+ wl_event_source_timer_update(txs->map_timer, 400); -+} -+ -+/* Fake getting "connection established" from the content streamer. */ -+static void -+fake_stream_opening_handler(void *data) -+{ -+ struct weston_transmitter_surface *txs = data; -+ -+ /* ...once the connection is up: */ -+ txs->status = WESTON_TRANSMITTER_STREAM_LIVE; -+ wl_signal_emit(&txs->stream_status_signal, txs); -+ -+ /* need to create the surface on the remote and set all state */ -+ transmitter_surface_gather_state(txs); -+ -+ fake_output_mapping(txs); -+} -+ -+/* Fake a callback from content streamer. */ -+static void -+fake_stream_opening(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter *txr = txs->remote->transmitter; -+ struct wl_event_loop *loop; -+ -+ loop = wl_display_get_event_loop(txr->compositor->wl_display); -+ wl_event_loop_add_idle(loop, fake_stream_opening_handler, txs); -+} -+ -+static struct weston_transmitter_surface * -+transmitter_surface_push_to_remote(struct weston_surface *ws, -+ struct weston_transmitter_remote *remote, -+ struct wl_listener *stream_status) -+{ -+ struct weston_transmitter_surface *txs; -+ -+ if (transmitter_surface_get(ws)) { -+ weston_log("Transmitter: surface %p already bound.\n", ws); -+ return NULL; -+ } -+ -+ txs = zalloc(sizeof (*txs)); -+ if (!txs) -+ return NULL; -+ -+ txs->remote = remote; -+ wl_signal_init(&txs->destroy_signal); -+ wl_list_insert(&remote->surface_list, &txs->link); -+ -+ txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING; -+ wl_signal_init(&txs->stream_status_signal); -+ wl_signal_add(&txs->stream_status_signal, stream_status); -+ -+ txs->surface = ws; -+ txs->surface_destroy_listener.notify = transmitter_surface_destroyed; -+ wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener); -+ -+ txs->apply_state_listener.notify = transmitter_surface_apply_state; -+ wl_signal_add(&ws->apply_state_signal, &txs->apply_state_listener); -+ -+ wl_list_init(&txs->sync_output_destroy_listener.link); -+ -+ wl_list_init(&txs->frame_callback_list); -+ wl_list_init(&txs->feedback_list); -+ -+ /* TODO: create the content stream connection... */ -+ fake_stream_opening(txs); -+ -+ return txs; -+} -+ -+static enum weston_transmitter_stream_status -+transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs) -+{ -+ return txs->status; -+} -+ -+static int -+conn_timer_handler(void *data) /* fake */ -+{ -+ struct weston_transmitter_remote *remote = data; -+ struct weston_transmitter_output_info info = { -+ WL_OUTPUT_SUBPIXEL_NONE, -+ WL_OUTPUT_TRANSFORM_NORMAL, -+ 1, -+ 0, 0, -+ 300, 200, -+ "fake", -+ { -+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, -+ 800, 600, -+ 51519, -+ { NULL, NULL } -+ } -+ }; -+ -+ weston_log("Transmitter connected to %s.\n", remote->addr); -+ remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -+ wl_signal_emit(&remote->connection_status_signal, remote); -+ -+ wl_event_source_remove(remote->conn_timer); -+ remote->conn_timer = NULL; -+ -+ /* Outputs and seats are dynamic, do not guarantee they are all -+ * present when signalling connection status. -+ */ -+ transmitter_remote_create_output(remote, &info); -+ transmitter_remote_create_seat(remote); -+ -+ return 0; -+} -+ -+static struct weston_transmitter_remote * -+transmitter_connect_to_remote(struct weston_transmitter *txr, -+ const char *addr, -+ struct wl_listener *status) -+{ -+ struct weston_transmitter_remote *remote; -+ struct wl_event_loop *loop; -+ -+ remote = zalloc(sizeof (*remote)); -+ if (!remote) -+ return NULL; -+ -+ remote->transmitter = txr; -+ wl_list_insert(&txr->remote_list, &remote->link); -+ remote->addr = strdup(addr); -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ wl_signal_init(&remote->connection_status_signal); -+ wl_signal_add(&remote->connection_status_signal, status); -+ wl_list_init(&remote->output_list); -+ wl_list_init(&remote->surface_list); -+ wl_list_init(&remote->seat_list); -+ -+ /* XXX: actually start connecting */ -+ weston_log("Transmitter connecting to %s...\n", addr); -+ /* fake it with a one second timer */ -+ loop = wl_display_get_event_loop(txr->compositor->wl_display); -+ remote->conn_timer = wl_event_loop_add_timer(loop, conn_timer_handler, -+ remote); -+ wl_event_source_timer_update(remote->conn_timer, 1000); -+ -+ return remote; -+} -+ -+static enum weston_transmitter_connection_status -+transmitter_remote_get_status(struct weston_transmitter_remote *remote) -+{ -+ return remote->status; -+} -+ -+static void -+transmitter_remote_destroy(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_surface *txs; -+ struct weston_transmitter_output *output, *otmp; -+ struct weston_transmitter_seat *seat, *stmp; -+ -+ /* Do not emit connection_status_signal. */ -+ -+ /* -+ * Must not touch remote->transmitter as it may be stale: -+ * the desctruction order between the shell and Transmitter is -+ * undefined. -+ */ -+ weston_log("Transmitter disconnecting from %s.\n", remote->addr); -+ -+ if (remote->conn_timer) -+ wl_event_source_remove(remote->conn_timer); -+ -+ if (!wl_list_empty(&remote->surface_list)) -+ weston_log("Transmitter warning: surfaces remain in %s.\n", -+ __func__); -+ wl_list_for_each(txs, &remote->surface_list, link) -+ txs->remote = NULL; -+ wl_list_remove(&remote->surface_list); -+ -+ wl_list_for_each_safe(seat, stmp, &remote->seat_list, link) -+ transmitter_seat_destroy(seat); -+ -+ wl_list_for_each_safe(output, otmp, &remote->output_list, link) -+ transmitter_output_destroy(output); -+ -+ free(remote->addr); -+ wl_list_remove(&remote->link); -+ -+ free(remote); -+} -+ -+/** Transmitter is destroyed on compositor shutdown. */ -+static void -+transmitter_compositor_destroyed(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_remote *remote; -+ struct weston_transmitter_surface *txs; -+ struct weston_transmitter *txr = -+ container_of(listener, struct weston_transmitter, -+ compositor_destroy_listener); -+ -+ assert(data == txr->compositor); -+ -+ /* may be called before or after shell cleans up */ -+ wl_list_for_each(remote, &txr->remote_list, link) { -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ transmitter_surface_zombify(txs); -+ } -+ } -+ -+ /* -+ * Remove the head in case the list is not empty, to avoid -+ * transmitter_remote_destroy() accessing freed memory if the shell -+ * cleans up after Transmitter. -+ */ -+ wl_list_remove(&txr->remote_list); -+ -+ weston_log("Transmitter terminating.\n"); -+ free(txr); -+} -+ -+static struct weston_transmitter * -+transmitter_get(struct weston_compositor *compositor) -+{ -+ struct wl_listener *listener; -+ struct weston_transmitter *txr; -+ -+ listener = wl_signal_get(&compositor->destroy_signal, -+ transmitter_compositor_destroyed); -+ if (!listener) -+ return NULL; -+ -+ txr = container_of(listener, struct weston_transmitter, -+ compositor_destroy_listener); -+ assert(compositor == txr->compositor); -+ -+ return txr; -+} -+ -+static const struct weston_transmitter_api transmitter_api_impl = { -+ transmitter_get, -+ transmitter_connect_to_remote, -+ transmitter_remote_get_status, -+ transmitter_remote_destroy, -+ transmitter_surface_push_to_remote, -+ transmitter_surface_get_stream_status, -+ transmitter_surface_destroy, -+ transmitter_surface_configure, -+}; -+ -+static void -+transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs, -+ uint32_t ivi_id) -+{ -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ -+ weston_log("%s(%p, %#x)\n", __func__, txs->surface, ivi_id); -+} -+ -+static void -+transmitter_surface_set_resize_callback( -+ struct weston_transmitter_surface *txs, -+ weston_transmitter_ivi_resize_handler_t cb, -+ void *data) -+{ -+ txs->resize_handler = cb; -+ txs->resize_handler_data = data; -+} -+ -+static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = { -+ transmitter_surface_set_ivi_id, -+ transmitter_surface_set_resize_callback, -+}; -+ -+WL_EXPORT int -+wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) -+{ -+ struct weston_transmitter *txr; -+ int ret; -+ -+ txr = zalloc(sizeof *txr); -+ if (!txr) -+ return -1; -+ -+ wl_list_init(&txr->remote_list); -+ -+ txr->compositor = compositor; -+ txr->compositor_destroy_listener.notify = -+ transmitter_compositor_destroyed; -+ wl_signal_add(&compositor->destroy_signal, -+ &txr->compositor_destroy_listener); -+ -+ ret = weston_plugin_api_register(compositor, -+ WESTON_TRANSMITTER_API_NAME, -+ &transmitter_api_impl, -+ sizeof(transmitter_api_impl)); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter API registration failed.\n"); -+ goto fail; -+ } -+ -+ ret = weston_plugin_api_register(compositor, -+ WESTON_TRANSMITTER_IVI_API_NAME, -+ &transmitter_ivi_api_impl, -+ sizeof(transmitter_ivi_api_impl)); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter IVI API registration failed.\n"); -+ goto fail; -+ } -+ -+ weston_log("Transmitter initialized.\n"); -+ -+ return 0; -+ -+fail: -+ wl_list_remove(&txr->compositor_destroy_listener.link); -+ free(txr); -+ -+ return -1; -+} -diff --git a/transmitter/plugin.h b/transmitter/plugin.h -new file mode 100644 -index 0000000..710b543 ---- /dev/null -+++ b/transmitter/plugin.h -@@ -0,0 +1,207 @@ -+/* -+ * Copyright (C) 2016 DENSO CORPORATION -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#ifndef WESTON_TRANSMITTER_PLUGIN_H -+#define WESTON_TRANSMITTER_PLUGIN_H -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+#include -+ -+#include "compositor.h" -+#include "transmitter_api.h" -+ -+struct weston_transmitter { -+ struct weston_compositor *compositor; -+ struct wl_listener compositor_destroy_listener; -+ -+ struct wl_list remote_list; /* transmitter_remote::link */ -+}; -+ -+struct weston_transmitter_remote { -+ struct weston_transmitter *transmitter; -+ struct wl_list link; -+ -+ char *addr; -+ -+ enum weston_transmitter_connection_status status; -+ struct wl_signal connection_status_signal; -+ -+ struct wl_list output_list; /* weston_transmitter_output::link */ -+ struct wl_list surface_list; /* weston_transmitter_surface::link */ -+ struct wl_list seat_list; /* weston_transmitter_seat::link */ -+ -+ struct wl_event_source *conn_timer; /* fake */ -+}; -+ -+struct weston_transmitter_surface { -+ struct weston_transmitter_remote *remote; -+ struct wl_list link; /* weston_transmitter_remote::surface_list */ -+ struct wl_signal destroy_signal; /* data: weston_transmitter_surface */ -+ -+ enum weston_transmitter_stream_status status; -+ struct wl_signal stream_status_signal; -+ -+ struct weston_surface *surface; -+ struct wl_listener surface_destroy_listener; -+ struct wl_listener apply_state_listener; -+ -+ weston_transmitter_ivi_resize_handler_t resize_handler; -+ void *resize_handler_data; -+ -+ struct weston_output *sync_output; -+ struct wl_listener sync_output_destroy_listener; -+ -+ struct wl_event_source *map_timer; /* fake */ -+ struct wl_event_source *frame_timer; /* fake */ -+ -+ int32_t attach_dx; /**< wl_surface.attach(buffer, dx, dy) */ -+ int32_t attach_dy; /**< wl_surface.attach(buffer, dx, dy) */ -+ struct wl_list frame_callback_list; /* weston_frame_callback::link */ -+ struct wl_list feedback_list; /* weston_presentation_feedback::link */ -+}; -+ -+struct weston_transmitter_output_info { -+ uint32_t subpixel; /* enum wl_output_subpixel */ -+ uint32_t transform; /* enum wl_output_transform */ -+ int32_t scale; -+ int32_t x; -+ int32_t y; -+ int32_t width_mm; -+ int32_t height_mm; -+ /* char *make; is WESTON_TRANSMITTER_OUTPUT_MAKE */ -+ char *model; -+ -+ struct weston_mode mode; -+}; -+ -+struct weston_transmitter_output { -+ struct weston_output base; -+ -+ struct weston_transmitter_remote *remote; -+ struct wl_list link; /* weston_transmitter_remote::output_list */ -+}; -+ -+struct weston_transmitter_seat { -+ struct weston_seat base; -+ struct wl_list link; -+ -+ /* pointer */ -+ wl_fixed_t pointer_surface_x; -+ wl_fixed_t pointer_surface_y; -+ -+ struct wl_listener get_pointer_listener; -+ struct weston_transmitter_surface *pointer_focus; -+ struct wl_listener pointer_focus_destroy_listener; -+ -+ struct wl_event_source *pointer_timer; /* fake */ -+ -+ double pointer_phase; /* fake */ -+ -+ /* keyboard */ -+ -+ /* touch */ -+}; -+ -+void -+transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, -+ int32_t width, int32_t height); -+ -+int -+transmitter_remote_create_output(struct weston_transmitter_remote *remote, -+ const struct weston_transmitter_output_info *info); -+ -+void -+transmitter_output_destroy(struct weston_transmitter_output *output); -+ -+int -+transmitter_remote_create_seat(struct weston_transmitter_remote *remote); -+ -+void -+transmitter_seat_destroy(struct weston_transmitter_seat *seat); -+ -+/* The below are the functions to be called from the network protocol -+ * input event handlers. -+ */ -+ -+void -+transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y); -+ -+void -+transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs); -+ -+void -+transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y); -+ -+void -+transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state); -+ -+void -+transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis, -+ wl_fixed_t value); -+ -+void -+transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat); -+ -+void -+transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, -+ uint32_t axis_source); -+ -+void -+transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis); -+ -+void -+transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, -+ uint32_t axis, -+ int32_t discrete); -+ -+/* Fake functions for mockup testing: */ -+ -+int -+transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, -+ struct weston_transmitter_surface *txs); -+ -+ -+#endif /* WESTON_TRANSMITTER_PLUGIN_H */ -diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h -new file mode 100644 -index 0000000..95d82ec ---- /dev/null -+++ b/transmitter/transmitter_api.h -@@ -0,0 +1,253 @@ -+/* -+ * Copyright (C) 2016 DENSO CORPORATION -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#ifndef WESTON_TRANSMITTER_API_H -+#define WESTON_TRANSMITTER_API_H -+ -+#include "plugin-registry.h" -+ -+#include -+ -+/** \file -+ * -+ * This is the Transmitter API published via weston_plugin_api_register(). -+ */ -+ -+struct weston_transmitter; -+struct weston_transmitter_remote; -+struct weston_transmitter_surface; -+ -+#define WESTON_TRANSMITTER_API_NAME "transmitter_v1" -+ -+/** See weston_transmitter_api::remote_get_status */ -+enum weston_transmitter_connection_status { -+ /** The connection hand-shake is not yet complete */ -+ WESTON_TRANSMITTER_CONNECTION_INITIALIZING, -+ -+ /** The connection is live and ready to be used. */ -+ WESTON_TRANSMITTER_CONNECTION_READY, -+ -+ /** The connection is dead. */ -+ WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, -+}; -+ -+/** See weston_transmitter_api::surface_get_stream_status */ -+enum weston_transmitter_stream_status { -+ /** The stream hand-shake is not yet complete. */ -+ WESTON_TRANSMITTER_STREAM_INITIALIZING, -+ -+ /** The stream is carrying surface content updates as needed. */ -+ WESTON_TRANSMITTER_STREAM_LIVE, -+ -+ /** The stream has failed and disconnected permanently. */ -+ WESTON_TRANSMITTER_STREAM_FAILED, -+}; -+ -+/** The Transmitter Base API -+ * -+ * Transmitter is a Weston plugin that provides remoting of weston_surfaces -+ * over the network. Shells use this API to create remote connections and -+ * push surfaces over the network. Shells are also responsible for relaying -+ * basic window state changes to Transmitter. -+ * -+ * In addition to the Transmitter Base API, shells also need to use a -+ * shell protocol specific Transmitter API to relay specific window state -+ * changes. -+ */ -+struct weston_transmitter_api { -+ /** Fetch the Transmitter plugin context -+ * -+ * \param compositor The compositor instance. -+ * \return The weston_transmitter context, which is always the same -+ * for the given compositor instance. -+ */ -+ struct weston_transmitter * -+ (*transmitter_get)(struct weston_compositor *compositor); -+ -+ /** -+ * Connect to a remote server via Transmitter. -+ * -+ * \param txr The Transmitter context. -+ * \param addr Address of the remote server. -+ * \param status Listener to inform of connection status changes. -+ * \return A handle to the remote connection, or NULL on failure. -+ * -+ * This call attempts to open a connection asynchronously. The -+ * connection is not usable until the listener signals it is ready. -+ * The listener may also signal that the connection failed instead. -+ * -+ * The listener callback argument is the weston_transmitter_remote -+ * returned by this function. Use remote_get_status() to fetch the -+ * current status. -+ * -+ * The address argument is a string in the form "host:port". -+ */ -+ struct weston_transmitter_remote * -+ (*connect_to_remote)(struct weston_transmitter *txr, -+ const char *addr, -+ struct wl_listener *status); -+ -+ /** -+ * Retrieve the connection status. -+ * -+ * If the status is WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, -+ * you have to shut the remote down completely. There is no automatic -+ * reconnect. -+ */ -+ enum weston_transmitter_connection_status -+ (*remote_get_status)(struct weston_transmitter_remote *remote); -+ -+ /** -+ * Destroy/disconnect a remote connection. -+ * -+ * Disconnects if connected, and destroys the connection. -+ * The connection status handler is not called. -+ * -+ * The caller is responsible for destroying all -+ * weston_transmitter_surfaces before calling this. -+ */ -+ void -+ (*remote_destroy)(struct weston_transmitter_remote *remote); -+ -+ /** Push a weston_surface to be transmitted to a remote. -+ * -+ * \param ws The surface to push. -+ * \param remote The remote connection to use. -+ * \param stream_status Listener for stream status changes. -+ * \return The Transmitter surface handle. -+ * -+ * The surface cannot be visible on the remote until the stream -+ * status listener signals WESTON_TRANSMITTER_STREAM_LIVE. After that, -+ * surface updates made by the application will be automatically -+ * streamed to the remote, and input events from the remote will be -+ * delivered to the application. -+ * -+ * The listener callback argument is the weston_transmitter_surface -+ * returned by this function. Use surface_get_stream_status() to -+ * fetch the current status. -+ */ -+ struct weston_transmitter_surface * -+ (*surface_push_to_remote)(struct weston_surface *ws, -+ struct weston_transmitter_remote *remote, -+ struct wl_listener *stream_status); -+ -+ /** -+ * Retrieve the surface content stream status. -+ * -+ * If the status is WESTON_TRANSMITTER_STREAM_FAILED, remoting the -+ * surface has stopped. There is no automatic retry. -+ */ -+ enum weston_transmitter_stream_status -+ (*surface_get_stream_status)(struct weston_transmitter_surface *txs); -+ -+ /** Stop remoting a weston_surface -+ * -+ * \param txs Transmitter surface handle to be stopped and freed. -+ * -+ * The surface stream status handler is not called. -+ */ -+ void -+ (*surface_destroy)(struct weston_transmitter_surface *txs); -+ -+ /** Notify of weston_surface being configured -+ * -+ * \param txs The Transmitter surface handle. -+ * \param dx The x delta given in wl_surface.attach request. -+ * \param dy The y delta given in wl_surface.attach request. -+ * -+ * Notifies Transmitter of new surface confguration. Transmitter will -+ * forward the arguments, window state, and reference the buffer for -+ * image transmission. -+ * -+ * Shells are meant to call this function for remoted surfaces in -+ * the weston_surface::configure handler. -+ * -+ * XXX: Is this necessary if we have weston_surface::apply_state_signal? -+ * -+ * Essentially this is just an elaborate way to forward dx,dy. -+ */ -+ void -+ (*surface_configure)(struct weston_transmitter_surface *txs, -+ int32_t dx, int32_t dy); -+}; -+ -+static inline const struct weston_transmitter_api * -+weston_get_transmitter_api(struct weston_compositor *compositor) -+{ -+ return weston_plugin_api_get(compositor, WESTON_TRANSMITTER_API_NAME, -+ sizeof(struct weston_transmitter_api)); -+} -+ -+#define WESTON_TRANSMITTER_IVI_API_NAME "transmitter_ivi_v1" -+ -+/** For relaying configure events from Transmitter to shell. */ -+typedef void (*weston_transmitter_ivi_resize_handler_t)(void *data, -+ int32_t width, -+ int32_t height); -+ -+/** The Transmitter IVI-shell API -+ * -+ * Contains the IVI-shell specifics required to remote an ivi-surface. -+ */ -+struct weston_transmitter_ivi_api { -+ /** Set IVI-id for a transmitter surface -+ * -+ * \param txs The transmitted surface. -+ * \param ivi_id The IVI-surface id as specified by the -+ * ivi_application.surface_create request. -+ */ -+ void -+ (*set_ivi_id)(struct weston_transmitter_surface *txs, uint32_t ivi_id); -+ -+ /** Set callback to relay configure events. -+ * -+ * \param txs The transmitted surface. -+ * \param cb The callback function pointer. -+ * \param data User data to be passed to the callback. -+ * -+ * The arguments to the callback function are user data, and width and -+ * height from the configure event from the remote compositor. The -+ * shell must relay this event to the application. -+ */ -+ void -+ (*set_resize_callback)(struct weston_transmitter_surface *txs, -+ weston_transmitter_ivi_resize_handler_t cb, -+ void *data); -+}; -+ -+static inline const struct weston_transmitter_ivi_api * -+weston_get_transmitter_ivi_api(struct weston_compositor *compositor) -+{ -+ return weston_plugin_api_get(compositor, -+ WESTON_TRANSMITTER_IVI_API_NAME, -+ sizeof(struct weston_transmitter_ivi_api)); -+} -+ -+/** Identifies outputs created by the Transmitter by make */ -+#define WESTON_TRANSMITTER_OUTPUT_MAKE "Weston-Transmitter" -+ -+/* Remote compositor/output are identified by model */ -+ -+#endif /* WESTON_TRANSMITTER_API_H */ --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0020-compositor-add-output-type-to-weston_output.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0018-compositor-add-output-type-to-weston_output.patch similarity index 100% rename from meta-agl-profile-graphical/recipes-graphics/wayland/weston/0020-compositor-add-output-type-to-weston_output.patch rename to meta-agl-profile-graphical/recipes-graphics/wayland/weston/0018-compositor-add-output-type-to-weston_output.patch diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0018-ivi-layout-Register-ivi-layout-interface-It-enables-.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0018-ivi-layout-Register-ivi-layout-interface-It-enables-.patch deleted file mode 100644 index b8f935712..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0018-ivi-layout-Register-ivi-layout-interface-It-enables-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 8e586a78c7e74f0faaddd02abbdfcf6879d0f096 Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Wed, 27 Sep 2017 09:09:17 +0900 -Subject: [PATCH 2/3] ivi-layout :Register ivi-layout-interface It enables to - use ivi-layout-interface without load module - -Signed-off-by: Wataru Mizuno ---- - ivi-shell/ivi-layout-export.h | 2 ++ - ivi-shell/ivi-layout.c | 4 ++++ - 2 files changed, 6 insertions(+) - -diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h -index 2317d6e..11ea874 100644 ---- a/ivi-shell/ivi-layout-export.h -+++ b/ivi-shell/ivi-layout-export.h -@@ -63,6 +63,8 @@ extern "C" { - #define IVI_SUCCEEDED (0) - #define IVI_FAILED (-1) - -+#define IVI_LAYOUT_API_NAME "ivi_layout_api_v1" -+ - struct ivi_layout_layer; - struct ivi_layout_screen; - struct ivi_layout_surface; -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index 64e4ead..602a42f 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -67,6 +67,7 @@ - #include "ivi-layout-export.h" - #include "ivi-layout-private.h" - #include "ivi-layout-shell.h" -+#include "plugin-registry.h" - - #include "shared/helpers.h" - #include "shared/os-compatibility.h" -@@ -2139,5 +2140,8 @@ load_controller_modules(struct weston_compositor *compositor, const char *module - p++; - } - -+ weston_plugin_api_register(compositor, IVI_LAYOUT_API_NAME, -+ &ivi_layout_interface, sizeof(struct ivi_layout_interface)); -+ - return 0; - } --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0023-compositor-drm-introduce-drm_get_dmafd_from_view.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0019-compositor-drm-introduce-drm_get_dmafd_from_view.patch similarity index 100% rename from meta-agl-profile-graphical/recipes-graphics/wayland/weston/0023-compositor-drm-introduce-drm_get_dmafd_from_view.patch rename to meta-agl-profile-graphical/recipes-graphics/wayland/weston/0019-compositor-drm-introduce-drm_get_dmafd_from_view.patch diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0019-transmitter-transmitter-plugin-for-waltham-protocol.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0019-transmitter-transmitter-plugin-for-waltham-protocol.patch deleted file mode 100644 index 6b4f276fe..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0019-transmitter-transmitter-plugin-for-waltham-protocol.patch +++ /dev/null @@ -1,2732 +0,0 @@ -From 0d114839f299b6a9e3f504e75c22d636222c3b20 Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Tue, 10 Apr 2018 15:23:02 +0900 -Subject: [PATCH 3/3] transmitter: transmitter plugin for waltham protocol - -The transmitter plugin enables weston to communicate with -remote site compositor over the ethernet. -Communication is done with waltham protocol which is the -wayland like IPC protocol. - -Signed-off-by: Wataru Mizuno ---- - Makefile.am | 11 +- - configure.ac | 12 + - transmitter/README | 108 +++-- - transmitter/input.c | 783 ++++++++++++++++++++++++++++++++- - transmitter/output.c | 139 +++++- - transmitter/plugin.c | 875 ++++++++++++++++++++++++++----------- - transmitter/plugin.h | 140 +++++- - transmitter/transmitter_api.h | 26 +- - transmitter/weston.ini.transmitter | 21 + - 9 files changed, 1763 insertions(+), 352 deletions(-) - create mode 100644 transmitter/weston.ini.transmitter - -diff --git a/Makefile.am b/Makefile.am -index 6cca875..2cb1920 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -306,6 +306,11 @@ westoninclude_HEADERS += \ - ivi-shell/ivi-layout-export.h - endif - -+if ENABLE_SURFACE_REMOTING -+westoninclude_HEADERS += \ -+ transmitter/transmitter_api.h -+endif -+ - if ENABLE_EGL - libweston_module_LTLIBRARIES += gl-renderer.la - gl_renderer_la_LDFLAGS = -module -avoid-version -@@ -507,8 +512,10 @@ module_LTLIBRARIES += transmitter.la - transmitter_la_LDFLAGS = -module -avoid-version - transmitter_la_CFLAGS = \ - $(COMPOSITOR_CFLAGS) \ -- $(AM_CFLAGS) --transmitter_la_LIBADD = $(COMPOSITOR_LIBS) -+ $(AM_CFLAGS) \ -+ $(WALTHAM_CFLAGS) -+transmitter_la_LIBADD = $(COMPOSITOR_LIBS) \ -+ -lwaltham - transmitter_la_SOURCES = \ - transmitter/plugin.c \ - transmitter/plugin.h \ -diff --git a/configure.ac b/configure.ac -index 6cf2883..4819e08 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -543,6 +543,18 @@ AC_ARG_ENABLE(surface-remoting, - AS_HELP_STRING([--enable-surface-remoting], - [support for surface remoting over network]),, - enable_surface_remoting=no) -+if test "x$enable_surface_remoting" != "xno"; then -+ PKG_CHECK_MODULES(WALTHAM, -+ waltham >= 0.1.0, -+ have_waltham=yes, -+ have_waltham=no) -+ if test "x$have_waltham" = "xno" -a "x$enable_surface_remoting" = "xyes"; then -+ AC_MSG_ERROR([surface_remoting support explicitly requested, but waltham couldn't be found]) -+ fi -+ if test "x$have_waltham" = "xyes"; then -+ enable_surface_remoting=yes -+ fi -+fi - AM_CONDITIONAL(ENABLE_SURFACE_REMOTING, test "x$enable_surface_remoting" = "xyes") - - -diff --git a/transmitter/README b/transmitter/README -index a7977ba..af80574 100644 ---- a/transmitter/README -+++ b/transmitter/README -@@ -1,45 +1,84 @@ --Testing Transmitter with ivi-shell -+Transmitter plugin - - The current implementation of Transmitter is a stub which interfaces to - other Weston parts appropriately, but all networking is just a mockup. - -+Sections in this file describe: -+- How to build -+- How to write weston.ini -+- How to test - -+How to build -+============ - Configure Weston with --enable-surface-remoting to build the Transmitter - plugin. - --In weston.ini, add 'transmitter.so' to the 'modules' key under '[core]', and --make sure the 'shell' is 'ivi-shell.so'. Follow the ivi-shell example --weston.ini for everything else. -- --When you start weston, the log should contain something like this: -- --[13:13:54.799] Loading module '/home/pq/local/lib/weston/ivi-shell.so' --[13:13:54.799] launching '/home/pq/local/libexec/weston-keyboard' --[13:13:54.799] Loading module '/home/pq/local/lib/weston/hmi-controller.so' --[13:13:54.799] Loading module '/home/pq/local/lib/weston/transmitter.so' --[13:13:54.799] Registered plugin API 'transmitter_v1' of size 48 --[13:13:54.799] Registered plugin API 'transmitter_ivi_v1' of size 16 --[13:13:54.799] Transmitter initialized. --[13:13:54.799] ivi-layout: Transmitter enabled. --[13:13:54.799] launching '/home/pq/build/weston/weston-ivi-shell-user-interface' --[13:13:54.799] hmi-controller: Transmitter enabled. --[13:13:54.799] Transmitter connecting to 0.0.0.0:66... --[13:13:55.800] Transmitter connected to 0.0.0.0:66. --[13:13:55.800] hmi-controller: connection status 0 --[13:13:55.800] Transmitter created output 'transmitter-0.0.0.0:66-1': Weston-Transmitter, transmitter-0.0.0.0:66-1, 0 --[13:13:55.800] Transmitter created seat=0x1c37bd0 'transmitter-0.0.0.0:66-default' --[13:13:55.800] Transmitter created pointer=0x1c38430 for seat 0x1c37bd0 --[13:13:55.800] transmitter_start_repaint_loop(transmitter-0.0.0.0:66-1) -- -- --If you have edited a client to have ivi-id >= 0xfaa01000, when you start that --client it should be "remoted" automatically and not appear on screen. -- --You can also manually start remoting: -+How to write weston.ini -+======================= -+To load transmitter plugin to weston, add 'transmitter.so' to the 'modules' -+key under '[core]', and make sure the 'shell' is 'ivi-shell.so'. -+ -+The destination of remoting is configured in weston.ini. -+Add output name, server address, port number, output's width and height key -+under '[remote-output]'. -+You can speficy multiple [remote-output]. -+ -+In details, see 'weston.ini.transmitter'. -+ -+How to test -+=========== -+You can use server side test application in waltham repository. -+ -+If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can -+see the log like this: -+ -+ [06:12:41.238] Loading module '/usr/lib64/weston/ivi-shell.so' -+ [06:12:41.245] launching '/usr/libexec/weston-keyboard' -+ [06:12:41.247] Loading module '/usr/lib64/weston/ivi-controller.so' -+ [06:12:41.252] Loading module '/usr/lib64/weston/ivi-input-controller.so' -+ [06:12:41.253] ivi-input-controller module loaded successfully! -+ [06:12:41.255] Loading module '/usr/lib64/weston/transmitter.so' -+ [06:12:41.260] Registered plugin API 'transmitter_v1' of size 88 -+ [06:12:41.260] Registered plugin API 'transmitter_ivi_v1' of size 16 -+ [06:12:41.260] Transmitter initialized. -+ [06:12:41.260] ivi-layout: Transmitter enabled. -+ [06:12:41.260] Transmitter weston_seat 0x14f8010 -+ [06:12:41.260] Transmitter created pointer=0x139a440 for seat 0x14f8010 -+ [06:12:41.261] Transmitter created keyboard=0x14f8160 for seat 0x14f8010 -+ [06:12:41.261] Transmitter created touch=0x1508750 for seat 0x14f8010 -+ -+The connection is established, you can see following debug messages: -+ -+ root@gr-mrb-64:~# debug: wth_connection_insert_new_object: new object id: 1 -+ debug: wth_connection_insert_new_object: new object id: 2 -+ 2017-07-19T06:14:31Z 00001000030000000100000002000000 wth_display_get_registry -+ debug: wth_connection_insert_new_object: new object id: 3 -+ 2017-07-19T06:14:31Z 00001000020000000100000003000000 wth_display_sync -+ debug: Message received on conn 0x1560340: (9) 40 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 4 -+ 2017-07-19T06:14:31Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthp_registry_bind -+ debug: Message received on conn 0x1560340: (9) 44 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 5 -+ 2017-07-19T06:14:31Z 000030000800000002000000010000000500000012000000777468705f626c6f625f666163746f72790001000000 wthp_registry_bind -+ debug: Message received on conn 0x1560340: (9) 48 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 1) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 6 -+ 2017-07-19T06:14:31Z 000034000800000002000000010000000600000015000000777468705f6976695f6170706c69636174696f6e0001000000 wthp_registry_bind -+ debug: Message received on conn 0x1560340: (11) 16 bytes -+ debug: wthp_callback_send_done(3, 0) (opcode 11) called. -+ sending wth_display.sync... -+ debug: wth_connection_insert_new_object: new object id: 7 -+ 2017-07-19T06:14:31Z 00001000020000000100000007000000 wth_display_sync -+ debug: Message received on conn 0x1560340: (11) 16 bytes -+ debug: wthp_callback_send_done(7, 0) (opcode 11) called. -+ ...sync done. -+ -+Start remoting : - - Start an IVI application. --- Move pointer onto the application window. --- Press Mod+Shift+space, and then 'k'. --- The window should disappear. -+- Put surface on backend output -+- Put surface on transmitter output - - Weston log will indicate remoting has started: - -@@ -48,6 +87,3 @@ Weston log will indicate remoting has started: - [13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6) - [13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 - --Once remoting has started, the mockup code will generate fake pointer input for --the window. This can be seen with e.g. weston-eventdemo, or running an --application with WAYLAND_DEBUG=client. -diff --git a/transmitter/input.c b/transmitter/input.c -index 0ba04d4..eeb7452 100644 ---- a/transmitter/input.c -+++ b/transmitter/input.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2016 DENSO CORPORATION -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -129,6 +130,79 @@ static const struct weston_pointer_grab_interface pointer_grab_impl = { - pointer_cancel_grab_handler, - }; - -+static void -+keyboard_grab_key(struct weston_keyboard_grab *grab, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+} -+ -+static void -+keyboard_grab_modifiers(struct weston_keyboard_grab *grab, -+ uint32_t serial, -+ uint32_t mods_depressed, -+ uint32_t mods_latched, -+ uint32_t mods_locked, -+ uint32_t group) -+{ -+} -+ -+static void -+keyboard_grab_cancel(struct weston_keyboard_grab *grab) -+{ -+} -+ -+static const struct weston_keyboard_grab_interface keyborad_grab_impl = { -+ keyboard_grab_key, -+ keyboard_grab_modifiers, -+ keyboard_grab_cancel -+}; -+ -+static void -+touch_grab_down_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+} -+ -+static void -+touch_grab_up_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id) -+{ -+} -+ -+static void -+touch_grab_motion_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+} -+ -+static void -+touch_grab_frame_handler(struct weston_touch_grab *grab) -+{ -+} -+ -+static void -+touch_grab_cancel_handler(struct weston_touch_grab *grab) -+{ -+} -+ -+static const struct weston_touch_grab_interface touch_grab_impl = { -+ touch_grab_down_handler, -+ touch_grab_up_handler, -+ touch_grab_motion_handler, -+ touch_grab_frame_handler, -+ touch_grab_cancel_handler, -+}; -+ -+ - /* The different ways to get pointer focus on a remoted surface: - * - * 1. Transmitter seat has pointer. The client has wl_pointer. Transmitter -@@ -207,7 +281,7 @@ seat_get_pointer_handler(struct wl_listener *listener, void *data) - if (wl_resource_get_client(surface) != client) - return; - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - assert(pointer); /* guaranteed by having pointer_focus */ - pointer_client = weston_pointer_get_pointer_client(pointer, client); - -@@ -235,13 +309,9 @@ transmitter_seat_create_pointer(struct weston_transmitter_seat *seat) - seat->pointer_focus = NULL; - wl_list_init(&seat->pointer_focus_destroy_listener.link); - -- weston_seat_init_pointer(&seat->base); -- -- seat->get_pointer_listener.notify = seat_get_pointer_handler; -- wl_signal_add(&seat->base.get_pointer_signal, -- &seat->get_pointer_listener); -+ weston_seat_init_pointer(seat->base); - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - - /* not exported: - * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */ -@@ -252,7 +322,7 @@ transmitter_seat_create_pointer(struct weston_transmitter_seat *seat) - wl_list_init(&pointer->output_destroy_listener.link); - - weston_log("Transmitter created pointer=%p for seat %p\n", -- pointer, &seat->base); -+ pointer, seat->base); - } - - static void -@@ -279,7 +349,7 @@ transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, - struct wl_list *focus_resource_list; - struct wl_resource *resource; - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - assert(pointer); - - assert(txs->surface); -@@ -299,8 +369,6 @@ transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, - seat->pointer_surface_x = surface_x; - seat->pointer_surface_y = surface_y; - -- pointer->focus_client = weston_pointer_get_pointer_client(pointer, -- client); - pointer->focus_serial = serial; - - /* pointer->focus is not used, because it is a weston_view, while -@@ -347,7 +415,7 @@ transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, - assert(txs->surface); - surface_resource = txs->surface->resource; - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - assert(pointer); - if (!pointer->focus_client) - return; -@@ -373,7 +441,7 @@ transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, - struct wl_resource *resource; - struct weston_transmitter_surface *txs; - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - assert(pointer); - - seat->pointer_surface_x = surface_x; -@@ -401,7 +469,27 @@ transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, - uint32_t button, - uint32_t state) - { -- assert(!"TODO"); -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_button(resource, serial, time, -+ button, state); -+ } - } - - void -@@ -410,7 +498,27 @@ transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, - uint32_t axis, - wl_fixed_t value) - { -- assert(!"TODO"); -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_axis(resource, time, -+ axis, value); -+ } - } - - void -@@ -418,7 +526,7 @@ transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat) - { - struct weston_pointer *pointer; - -- pointer = weston_seat_get_pointer(&seat->base); -+ pointer = weston_seat_get_pointer(seat->base); - if (pointer) - weston_pointer_send_frame(pointer); - } -@@ -427,7 +535,7 @@ void - transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, - uint32_t axis_source) - { -- assert(!"TODO"); -+ /* ToDo : implement axis event handling */ - } - - void -@@ -435,7 +543,7 @@ transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, - uint32_t time, - uint32_t axis) - { -- assert(!"TODO"); -+ /* ToDo : implement axis event handling */ - } - - void -@@ -443,7 +551,222 @@ transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, - uint32_t axis, - int32_t discrete) - { -- assert(!"TODO"); -+ /* ToDo : implement axis event handling */ -+} -+ -+static void -+transmitter_seat_create_keyboard(struct weston_transmitter_seat *seat) -+{ -+ struct weston_keyboard *keyboard; -+ -+ seat->keyboard_focus = NULL; -+ weston_seat_init_keyboard(seat->base, NULL); -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ -+ keyboard->default_grab.interface = &keyborad_grab_impl; -+ -+ weston_log("Transmitter created keyboard=%p for seat %p\n", -+ keyboard, seat->base); -+} -+ -+static void -+transmitter_seat_keyboard_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ struct wl_array *keys) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ seat->keyboard_focus = txs; -+ wl_array_copy(&keyboard->keys, keys); -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_keyboard_send_enter(resource, -+ serial, -+ surface_resource, -+ &keyboard->keys); -+ } -+ } -+} -+ -+static void -+transmitter_seat_keyboard_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_keyboard_send_leave(resource, -+ serial, -+ surface_resource); -+ } -+ } -+} -+ -+static void -+transmitter_seat_keyboard_key(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->keyboard_focus->surface->resource)) { -+ wl_keyboard_send_key(resource, -+ serial, -+ time, -+ key, -+ state); -+ } -+ } -+} -+ -+static void -+transmitter_seat_create_touch(struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ -+ seat->touch_focus = NULL; -+ weston_seat_init_touch(seat->base); -+ -+ touch = weston_seat_get_touch(seat->base); -+ -+ touch->default_grab.interface = &touch_grab_impl; -+ -+ weston_log("Transmitter created touch=%p for seat %p\n", -+ touch, seat->base); -+} -+ -+static void -+transmitter_seat_touch_down (struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ struct weston_transmitter_surface *txs, -+ int32_t touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ seat->touch_focus = txs; -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_touch_send_down(resource, serial, time, -+ surface_resource, -+ touch_id, x, y); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_up (struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ int32_t touch_id) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_up(resource, serial, time, touch_id); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_motion (struct weston_transmitter_seat *seat, -+ uint32_t time, -+ int32_t touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_motion(resource, time, touch_id, x, y); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_frame (struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_frame(resource); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_cancel (struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_cancel(resource); -+ } -+ } - } - - static char * -@@ -462,9 +785,7 @@ transmitter_seat_destroy(struct weston_transmitter_seat *seat) - { - wl_list_remove(&seat->link); - -- weston_log("Transmitter destroy seat=%p\n", &seat->base); -- -- weston_seat_release(&seat->base); -+ weston_log("Transmitter destroy seat=%p\n", seat->base); - - wl_list_remove(&seat->get_pointer_listener.link); - wl_list_remove(&seat->pointer_focus_destroy_listener.link); -@@ -475,11 +796,406 @@ transmitter_seat_destroy(struct weston_transmitter_seat *seat) - free(seat); - } - -+static void -+pointer_handle_enter(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ struct wthp_surface *surface, -+ wth_fixed_t surface_x, -+ wth_fixed_t surface_y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ if (txs != seat->pointer_focus) -+ transmitter_seat_pointer_leave(seat, serial, seat->pointer_focus); -+ transmitter_seat_pointer_enter(seat, serial, txs, -+ surface_x, surface_y); -+ } -+ } -+} -+ -+static void -+pointer_handle_leave(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ struct wthp_surface *surface) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_pointer_leave(seat, serial, txs); -+ } -+ } -+} -+ -+static void -+pointer_handle_motion(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ wth_fixed_t surface_x, -+ wth_fixed_t surface_y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_pointer_motion(seat, time, -+ surface_x, -+ surface_y); -+} -+ -+static void -+pointer_handle_button(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_pointer_button(seat, serial, -+ time, button, -+ state); -+} -+ -+static void -+pointer_handle_axis(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ uint32_t axis, wth_fixed_t value) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_pointer_axis(seat, time, -+ axis, value); -+} -+ -+static void -+pointer_handle_frame(struct wthp_pointer *wthp_pointer) -+{ -+ /* ToDo : implement pointer handle frame */ -+} -+ -+static void -+pointer_handle_axis_source(struct wthp_pointer *wthp_pointer, -+ uint32_t axis_source) -+{ -+ /* ToDo : implement pointer handle axis source */ -+} -+ -+static void -+pointer_handle_axis_stop(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ uint32_t axis) -+{ -+ /* ToDo : implement pointer handle axis stop */ -+} -+ -+static void -+pointer_handle_axis_discrete(struct wthp_pointer *wthp_pointer, -+ uint32_t axis, -+ int32_t discrete) -+{ -+ /* ToDo : implement pointer handle axis discrete */ -+} -+ -+static const struct wthp_pointer_listener pointer_listener = { -+ pointer_handle_enter, -+ pointer_handle_leave, -+ pointer_handle_motion, -+ pointer_handle_button, -+ pointer_handle_axis, -+ pointer_handle_frame, -+ pointer_handle_axis_source, -+ pointer_handle_axis_stop, -+ pointer_handle_axis_discrete -+}; -+ -+static void -+keyboard_handle_keymap(struct wthp_keyboard * wthp_keyboard, -+ uint32_t format, -+ uint32_t keymap_sz, -+ void * keymap) -+{ -+ /* ToDo : implement keyboard handle keymap */ -+} -+ -+static void -+keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ struct wthp_surface *surface, -+ struct wth_array *keys) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ struct wl_array *wl_key = (struct wl_array *)malloc(sizeof(struct wl_array)); -+ -+ wl_key->size = keys->size; -+ wl_key->alloc = keys->alloc; -+ wl_key->data = keys->data; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ //transmitter_seat_keyboard_enter(seat, serial, txs, keys); -+ transmitter_seat_keyboard_enter(seat, serial, txs, wl_key); -+ } -+ } -+ free(wl_key); -+} -+ -+static void -+keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ struct wthp_surface *surface) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_keyboard_leave(seat, serial, txs); -+ } -+ } -+} -+ -+static void -+keyboard_handle_key(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_keyboard_key(seat, serial, time, key, state); -+} -+ -+static void -+keyboard_handle_modifiers(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ uint32_t mods_depressed, -+ uint32_t mods_latched, -+ uint32_t mods_locked, -+ uint32_t group) -+{ -+ weston_log("keyboard_handle_modifiers\n"); -+} -+ -+static void -+keyboard_handle_repeat_info(struct wthp_keyboard *wthp_keyboard, -+ int32_t rate, -+ int32_t delay) -+{ -+ weston_log("keyboard_handle_repeat_info\n"); -+} -+ -+static const struct wthp_keyboard_listener keyboard_listener = { -+ keyboard_handle_keymap, -+ keyboard_handle_enter, -+ keyboard_handle_leave, -+ keyboard_handle_key, -+ keyboard_handle_modifiers, -+ keyboard_handle_repeat_info -+}; -+ -+static void -+touch_handle_down (struct wthp_touch * wthp_touch, -+ uint32_t serial, -+ uint32_t time, -+ struct wthp_surface * surface, -+ int32_t id, -+ wth_fixed_t x, -+ wth_fixed_t y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_touch_down(seat, serial, time, -+ txs, id, x, y); -+ } -+ } -+} -+ -+static void -+touch_handle_up (struct wthp_touch * wthp_touch, -+ uint32_t serial, -+ uint32_t time, -+ int32_t id) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_touch_up(seat, serial, time, id); -+} -+ -+static void -+touch_handle_motion (struct wthp_touch * wthp_touch, -+ uint32_t time, -+ int32_t id, -+ wth_fixed_t x, -+ wth_fixed_t y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_touch_motion(seat, time, id, x, y); -+} -+ -+ -+static void -+touch_handle_frame (struct wthp_touch * wthp_touch) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_touch_frame(seat); -+} -+ -+static void -+touch_handle_cancel (struct wthp_touch * wthp_touch) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = container_of(seat_list->next, -+ struct weston_transmitter_seat, link); -+ -+ transmitter_seat_touch_cancel(seat); -+} -+ -+ -+static const struct wthp_touch_listener touch_listener = { -+ touch_handle_down, -+ touch_handle_up, -+ touch_handle_motion, -+ touch_handle_frame, -+ touch_handle_cancel -+}; -+ -+void -+seat_capabilities(struct wthp_seat *wthp_seat, -+ enum wthp_seat_capability caps) -+{ -+ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)wthp_seat); -+ -+ weston_log("seat_capabilities\n"); -+ -+ if ((caps & WTHP_SEAT_CAPABILITY_POINTER) && !dpy->pointer) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_POINTER\n"); -+ dpy->pointer = wthp_seat_get_pointer(dpy->seat); -+ wthp_pointer_set_listener(dpy->pointer, &pointer_listener, dpy); -+ } -+ if ((caps & WTHP_SEAT_CAPABILITY_KEYBOARD) && !dpy->keyboard) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_KEYBOARD\n"); -+ dpy->keyboard = wthp_seat_get_keyboard(dpy->seat); -+ wthp_keyboard_set_listener(dpy->keyboard, &keyboard_listener, dpy); -+ } -+ if ((caps & WTHP_SEAT_CAPABILITY_TOUCH) && !dpy->touch) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_TOUCH\n"); -+ dpy->touch = wthp_seat_get_touch(dpy->seat); -+ wthp_touch_set_listener(dpy->touch, &touch_listener, dpy); -+ } -+} -+ - int - transmitter_remote_create_seat(struct weston_transmitter_remote *remote) - { - struct weston_transmitter_seat *seat = NULL; - char *name = NULL; -+ struct weston_seat *weston_seat = NULL; - - seat = zalloc(sizeof *seat); - if (!seat) -@@ -493,6 +1209,24 @@ transmitter_remote_create_seat(struct weston_transmitter_remote *remote) - if (!name) - goto fail; - -+ -+ if (wl_list_empty(&remote->transmitter->compositor->seat_list)) { -+ weston_seat = zalloc(sizeof *weston_seat); -+ if (!weston_seat) -+ goto fail; -+ -+ weston_seat_init(weston_seat, remote->transmitter->compositor, name); -+ seat->base = weston_seat; -+ weston_log("Transmitter created seat=%p \n", &seat->base); -+ } else { -+ wl_list_for_each(weston_seat, &remote->transmitter->compositor->seat_list, link) { -+ weston_log("Transmitter weston_seat %p\n", weston_seat); -+ seat->base = weston_seat; -+ } -+ } -+ -+ free(name); -+#if DEBUG - weston_seat_init(&seat->base, remote->transmitter->compositor, name); - free(name); - -@@ -515,9 +1249,12 @@ transmitter_remote_create_seat(struct weston_transmitter_remote *remote) - - weston_log("Transmitter created seat=%p '%s'\n", - &seat->base, seat->base.seat_name); -+#endif - - /* XXX: mirror remote capabilities */ - transmitter_seat_create_pointer(seat); -+ transmitter_seat_create_keyboard(seat); -+ transmitter_seat_create_touch(seat); - - wl_list_insert(&remote->seat_list, &seat->link); - -@@ -582,7 +1319,7 @@ transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, - - if (!seat->pointer_timer) { - /* schedule timer for motion */ -- loop = wl_display_get_event_loop(seat->base.compositor->wl_display); -+ loop = wl_display_get_event_loop(seat->base->compositor->wl_display); - seat->pointer_timer = wl_event_loop_add_timer(loop, - fake_pointer_timer_handler, seat); - wl_event_source_timer_update(seat->pointer_timer, 100); -diff --git a/transmitter/output.c b/transmitter/output.c -index 6a78721..a3f8ed1 100644 ---- a/transmitter/output.c -+++ b/transmitter/output.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2016 DENSO CORPORATION -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -73,7 +74,7 @@ make_model(struct weston_transmitter_remote *remote, int name) - { - char *str; - -- if (asprintf(&str, "transmitter-%s-%d", remote->addr, name) < 0) -+ if (asprintf(&str, "transmitter-%s:%s-%d", remote->addr, remote->port, name) < 0) - return NULL; - - return str; -@@ -124,8 +125,6 @@ free_mode_list(struct wl_list *mode_list) - void - transmitter_output_destroy(struct weston_transmitter_output *output) - { -- weston_log("Transmitter destroying output '%s'\n", output->base.name); -- - wl_list_remove(&output->link); - - free_mode_list(&output->base.mode_list); -@@ -145,46 +144,150 @@ transmitter_output_destroy_(struct weston_output *base) - transmitter_output_destroy(output); - } - -+ - static void - transmitter_start_repaint_loop(struct weston_output *base) - { -- weston_log("%s(%s)\n", __func__, base->name); -+ struct timespec ts; -+ struct weston_transmitter_output *output = to_transmitter_output(base); -+ -+ weston_compositor_read_presentation_clock(output->base.compositor, &ts); -+ weston_output_finish_frame(&output->base, &ts, 0); -+} -+ -+static int -+transmitter_check_output(struct weston_transmitter_surface *txs, -+ struct weston_compositor *compositor) -+{ -+ struct weston_output *def_output = container_of(compositor->output_list.next, -+ struct weston_output, link); -+ struct weston_view *view; -+ -+ wl_list_for_each_reverse(view, &compositor->view_list, link) { -+ if (view->output == def_output) { -+ if (view->surface == txs->surface) -+ return 1; -+ } -+ } -+ -+ return 0; - } - - static int - transmitter_output_repaint(struct weston_output *base, - pixman_region32_t *damage) - { -- weston_log("%s(%s)\n", __func__, base->name); -+ struct weston_transmitter_output* output = to_transmitter_output(base); -+ struct weston_transmitter_remote* remote = output->remote; -+ struct weston_transmitter* txr = remote->transmitter; -+ struct weston_transmitter_api* transmitter_api = -+ weston_get_transmitter_api(txr->compositor); -+ struct weston_transmitter_surface* txs; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_view *view; -+ bool found_output = false; -+ -+ if (!output->from_frame_signal) -+ return 0; -+ -+ output->from_frame_signal = false; -+ -+ /* -+ * Pick up weston_view in transmitter_output and check weston_view's surface -+ * If the surface hasn't been conbined to weston_transmitter_surface, -+ * then call push_to_remote. -+ * If the surface has already been combined, call gather_state. -+ */ -+ if (wl_list_empty(&compositor->view_list)) -+ goto out; -+ -+ wl_list_for_each_reverse(view, &compositor->view_list, link) { -+ bool found_surface = false; -+ if (view->output == &output->base) { -+ found_output = true; -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == view->surface) { -+ found_surface = true; -+ if (!transmitter_check_output(txs, compositor)) -+ break; -+ -+ if (!txs->wthp_surf) -+ transmitter_api->surface_push_to_remote -+ (view->surface, remote, NULL); -+ transmitter_api->surface_gather_state(txs); -+ break; -+ } -+ } -+ if (!found_surface) -+ transmitter_api->surface_push_to_remote(view->surface, -+ remote, NULL); -+ } -+ } -+ if (!found_output) -+ goto out; - -- return -1; -+ return 0; -+ -+out: -+ transmitter_start_repaint_loop(base); -+ -+ return 0; -+} -+ -+static void -+transmitter_output_enable(struct weston_output *base) -+{ -+ struct weston_transmitter_output *output = to_transmitter_output(base); -+ -+ -+ output->base.assign_planes = NULL; -+ output->base.set_backlight = NULL; -+ output->base.set_dpms = NULL; -+ output->base.switch_mode = NULL; -+} -+ -+static void -+transmitter_output_frame_handler(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_output *output; -+ int ret; -+ -+ output = container_of(listener, struct weston_transmitter_output, -+ frame_listener); -+ output->from_frame_signal = true; -+ -+ ret = transmitter_output_repaint(&output->base, NULL); - } - - int --transmitter_remote_create_output( -- struct weston_transmitter_remote *remote, -- const struct weston_transmitter_output_info *info) -+transmitter_remote_create_output(struct weston_transmitter_remote *remote, -+ const struct weston_transmitter_output_info *info) - { - struct weston_transmitter_output *output; -+ struct weston_transmitter *txr = remote->transmitter; -+ struct weston_output *def_output; - - output = zalloc(sizeof *output); - if (!output) - return -1; - -+ output->parent.draw_initial_frame = true; -+ - output->base.subpixel = info->subpixel; - - output->base.name = make_model(remote, 1); - output->base.make = strdup(WESTON_TRANSMITTER_OUTPUT_MAKE); - output->base.model = make_model(remote, 1); - output->base.serial_number = strdup("0"); -- -+ /* x and y is fake value */ - wl_list_init(&output->base.mode_list); - if (make_mode_list(&output->base.mode_list, info) < 0) - goto fail; - - output->base.current_mode = get_current_mode(&output->base.mode_list); -+ output->base.height = output->base.current_mode->height; -+ output->base.width = output->base.current_mode->width; - /* WL_OUTPUT_MODE_CURRENT already set */ -- - weston_output_init(&output->base, remote->transmitter->compositor); - - /* -@@ -200,7 +303,7 @@ transmitter_remote_create_output( - * for this output, since we must not involve input device management - * or color management or any kind of local management. - */ -- -+ output->base.enable = transmitter_output_enable; - output->base.start_repaint_loop = transmitter_start_repaint_loop; - output->base.repaint = transmitter_output_repaint; - output->base.destroy = transmitter_output_destroy_; -@@ -212,13 +315,19 @@ transmitter_remote_create_output( - - output->base.native_mode = output->base.current_mode; - output->base.native_scale = output->base.current_scale; -+ output->base.scale = 1; -+ output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL; - - output->remote = remote; - wl_list_insert(&remote->output_list, &output->link); - -- weston_log("Transmitter created output '%s': %s, %s, %s\n", -- output->base.name, output->base.make, output->base.model, -- output->base.serial_number); -+ weston_output_enable(&output->base); -+ -+ output->frame_listener.notify = transmitter_output_frame_handler; -+ def_output = container_of(txr->compositor->output_list.next, -+ struct weston_output, link); -+ wl_signal_add(&def_output->frame_signal, &output->frame_listener); -+ output->from_frame_signal = false; - - return 0; - -diff --git a/transmitter/plugin.c b/transmitter/plugin.c -index c5e56d3..1ebd1ef 100644 ---- a/transmitter/plugin.c -+++ b/transmitter/plugin.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2016 DENSO CORPORATION -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -34,8 +35,23 @@ - #include "helpers.h" - #include "timespec-util.h" - -+#include "compositor/weston.h" - #include "plugin.h" - #include "transmitter_api.h" -+#include "plugin-registry.h" -+#include "ivi-shell/ivi-layout-export.h" -+ -+/* waltham */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_EPOLL_WATCHES 2 -+#define ESTABLISH_CONNECTION_PERIOD 2000 -+#define RETRY_CONNECTION_PERIOD 5000 - - /* XXX: all functions and variables with a name, and things marked with a - * comment, containing the word "fake" are mockups that need to be -@@ -69,63 +85,6 @@ transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, - txs->resize_handler(txs->resize_handler_data, width, height); - } - --static int --frame_callback_handler(void *data) /* fake */ --{ -- struct weston_transmitter_surface *txs = data; -- struct weston_frame_callback *cb, *cnext; -- struct weston_output *output; -- struct weston_compositor *compositor; -- uint32_t frame_time; -- uint32_t presented_flags; -- int32_t refresh_nsec; -- struct timespec stamp; -- -- compositor = txs->remote->transmitter->compositor; -- output = txs->sync_output; -- -- /* wl_surface.enter should arrive before any frame callbacks, -- * but remote might send frame callbacks for non-visible too. -- */ -- if (!output) -- return 0; -- -- /* XXX: eeeew */ -- frame_time = weston_compositor_get_time(); -- -- wl_list_for_each_safe(cb, cnext, &txs->frame_callback_list, link) { -- wl_callback_send_done(cb->resource, frame_time); -- wl_resource_destroy(cb->resource); -- } -- -- presented_flags = 0; -- refresh_nsec = millihz_to_nsec(output->current_mode->refresh); -- /* XXX: waaahhhahaa */ -- weston_compositor_read_presentation_clock(compositor, &stamp); -- weston_presentation_feedback_present_list(&txs->feedback_list, -- output, refresh_nsec, &stamp, -- output->msc, -- presented_flags); -- -- return 0; --} -- --static void --fake_frame_callback(struct weston_transmitter_surface *txs) --{ -- struct weston_transmitter *txr = txs->remote->transmitter; -- struct wl_event_loop *loop; -- -- if (!txs->frame_timer) { -- loop = wl_display_get_event_loop(txr->compositor->wl_display); -- txs->frame_timer = -- wl_event_loop_add_timer(loop, -- frame_callback_handler, txs); -- } -- -- wl_event_source_timer_update(txs->frame_timer, 85); --} -- - static void - transmitter_surface_configure(struct weston_transmitter_surface *txs, - int32_t dx, int32_t dy) -@@ -139,37 +98,75 @@ transmitter_surface_configure(struct weston_transmitter_surface *txs, - } - - static void --transmitter_surface_gather_state(struct weston_transmitter_surface *txs) -+buffer_send_complete(struct wthp_buffer *b, uint32_t serial) - { -- weston_log("Transmitter: update surface %p (%d, %d), %d cb\n", -- txs->surface, txs->attach_dx, txs->attach_dy, -- wl_list_length(&txs->surface->frame_callback_list)); -- -- wl_list_insert_list(&txs->frame_callback_list, -- &txs->surface->frame_callback_list); -- wl_list_init(&txs->surface->frame_callback_list); -- -- wl_list_insert_list(&txs->feedback_list, &txs->surface->feedback_list); -- wl_list_init(&txs->surface->feedback_list); -- -- /* TODO: transmit surface state to remote */ -- -- txs->attach_dx = 0; -- txs->attach_dy = 0; -+ if (b) -+ wthp_buffer_destroy(b); - } - --/** weston_surface apply state signal handler */ -+static const struct wthp_buffer_listener buffer_listener = { -+ buffer_send_complete -+}; -+ - static void --transmitter_surface_apply_state(struct wl_listener *listener, void *data) -+transmitter_surface_gather_state(struct weston_transmitter_surface *txs) - { -- struct weston_transmitter_surface *txs = -- container_of(listener, struct weston_transmitter_surface, -- apply_state_listener); -- -- assert(data == NULL); -+ struct weston_transmitter_remote *remote = txs->remote; -+ struct waltham_display *dpy = remote->display; - -- transmitter_surface_gather_state(txs); -- fake_frame_callback(txs); -+ if(!dpy->running) { -+ if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) { -+ remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED; -+ wl_event_source_timer_update(remote->retry_timer, 1); -+ } -+ } -+ else { -+ /* TODO: transmit surface state to remote */ -+ /* The buffer must be transmitted to remote side */ -+ -+ /* waltham */ -+ struct weston_surface *surf = txs->surface; -+ struct weston_compositor *comp = surf->compositor; -+ int32_t width = 100; -+ int32_t height = 100; -+ int32_t stride; -+ int ret = 0; -+ void *pixels; -+ -+// stride = surf->width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); -+ stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); -+// weston_log("width %d\n", surf->width); -+// weston_log("height %d\n", surf->height); -+// weston_log("stride %d\n", stride); -+ pixels = malloc(stride * height); -+ -+ ret = weston_surface_copy_content(surf, pixels, -+ (stride * height), 0, 0, -+ width, height); -+ if(ret < 0) -+ fprintf(stderr, "failed to get surface content\n"); -+ -+ /* fake sending buffer */ -+ txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory, -+ (stride * height), -+ pixels, -+ width, -+ height, -+ stride, -+ PIXMAN_FORMAT_BPP(comp->read_format)); -+ -+ wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs); -+ -+ wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy); -+ //wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); -+ wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, width, height); -+ wthp_surface_commit(txs->wthp_surf); -+ -+ wth_connection_flush(remote->display->connection); -+ -+ txs->attach_dx = 0; -+ txs->attach_dy = 0; -+ } - } - - /** Mark the weston_transmitter_surface dead. -@@ -181,8 +178,7 @@ transmitter_surface_apply_state(struct wl_listener *listener, void *data) - static void - transmitter_surface_zombify(struct weston_transmitter_surface *txs) - { -- struct weston_frame_callback *framecb, *cnext; -- -+ struct weston_transmitter_remote *remote; - /* may be called multiple times */ - if (!txs->surface) - return; -@@ -190,20 +186,17 @@ transmitter_surface_zombify(struct weston_transmitter_surface *txs) - wl_signal_emit(&txs->destroy_signal, txs); - - wl_list_remove(&txs->surface_destroy_listener.link); -- weston_log("Transmitter unbound surface %p.\n", txs->surface); - txs->surface = NULL; - - wl_list_remove(&txs->sync_output_destroy_listener.link); -- wl_list_remove(&txs->apply_state_listener.link); -- -- if (txs->map_timer) -- wl_event_source_remove(txs->map_timer); -- if (txs->frame_timer) -- wl_event_source_remove(txs->frame_timer); - -- weston_presentation_feedback_discard_list(&txs->feedback_list); -- wl_list_for_each_safe(framecb, cnext, &txs->frame_callback_list, link) -- wl_resource_destroy(framecb->resource); -+ remote = txs->remote; -+ if (!remote->display->compositor) -+ weston_log("remote->compositor is NULL\n"); -+ if (txs->wthp_surf) -+ wthp_surface_destroy(txs->wthp_surf); -+ if (txs->wthp_ivi_surface) -+ wthp_ivi_surface_destroy(txs->wthp_ivi_surface); - - /* In case called from destroy_transmitter() */ - txs->remote = NULL; -@@ -231,25 +224,6 @@ transmitter_surface_destroyed(struct wl_listener *listener, void *data) - transmitter_surface_zombify(txs); - } - --static struct weston_transmitter_surface * --transmitter_surface_get(struct weston_surface *ws) --{ -- struct wl_listener *listener; -- struct weston_transmitter_surface *txs; -- -- listener = wl_signal_get(&ws->destroy_signal, -- transmitter_surface_destroyed); -- -- if (!listener) -- return NULL; -- -- txs = container_of(listener, struct weston_transmitter_surface, -- surface_destroy_listener); -- assert(ws == txs->surface); -- -- return txs; --} -- - static void - sync_output_destroy_handler(struct wl_listener *listener, void *data) - { -@@ -265,84 +239,48 @@ sync_output_destroy_handler(struct wl_listener *listener, void *data) - } - - static void --fake_input(struct weston_transmitter_surface *txs) --{ -- struct wl_list *seat_list = &txs->remote->seat_list; -- struct weston_transmitter_seat *seat; -- -- assert(wl_list_length(seat_list) == 1); -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -- -- transmitter_seat_fake_pointer_input(seat, txs); --} -- --/* fake receiving wl_surface.enter(output) */ --static int --map_timer_handler(void *data) --{ -- struct weston_transmitter_surface *txs = data; -- struct weston_transmitter_output *output; -- -- assert(!wl_list_empty(&txs->remote->output_list)); -- -- output = container_of(txs->remote->output_list.next, -- struct weston_transmitter_output, link); -- -- txs->sync_output = &output->base; -- txs->sync_output_destroy_listener.notify = sync_output_destroy_handler; -- wl_list_remove(&txs->sync_output_destroy_listener.link); -- wl_signal_add(&txs->sync_output->destroy_signal, -- &txs->sync_output_destroy_listener); -- -- weston_surface_force_output(txs->surface, txs->sync_output); -- -- weston_log("Transmitter: surface %p entered output %s\n", -- txs->surface, txs->sync_output->name); -- -- fake_frame_callback(txs); -- fake_input(txs); -- -- return 0; --} -- --/* Fake a delay for the remote end to map the surface to an output */ --static void --fake_output_mapping(struct weston_transmitter_surface *txs) --{ -- struct weston_transmitter *txr = txs->remote->transmitter; -- struct wl_event_loop *loop; -- -- loop = wl_display_get_event_loop(txr->compositor->wl_display); -- txs->map_timer = wl_event_loop_add_timer(loop, map_timer_handler, txs); -- wl_event_source_timer_update(txs->map_timer, 400); --} -- --/* Fake getting "connection established" from the content streamer. */ --static void --fake_stream_opening_handler(void *data) --{ -- struct weston_transmitter_surface *txs = data; -- -- /* ...once the connection is up: */ -- txs->status = WESTON_TRANSMITTER_STREAM_LIVE; -- wl_signal_emit(&txs->stream_status_signal, txs); -- -- /* need to create the surface on the remote and set all state */ -- transmitter_surface_gather_state(txs); -- -- fake_output_mapping(txs); --} -- --/* Fake a callback from content streamer. */ --static void --fake_stream_opening(struct weston_transmitter_surface *txs) -+transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs) - { -- struct weston_transmitter *txr = txs->remote->transmitter; -- struct wl_event_loop *loop; -- -- loop = wl_display_get_event_loop(txr->compositor->wl_display); -- wl_event_loop_add_idle(loop, fake_stream_opening_handler, txs); -+ struct weston_transmitter_remote *remote = txs->remote; -+ struct waltham_display *dpy = remote->display; -+ struct weston_surface *ws; -+ struct ivi_layout_surface **pp_surface = NULL; -+ struct ivi_layout_surface *ivi_surf = NULL; -+ int32_t surface_length = 0; -+ int32_t ret = 0; -+ int32_t i = 0; -+ -+ ret = txs->lyt->get_surfaces(&surface_length, &pp_surface); -+ if(!ret) -+ weston_log("No ivi_surface\n"); -+ -+ ws = txs->surface; -+ -+ for(i = 0; i < surface_length; i++) { -+ ivi_surf = pp_surface[i]; -+ if (ivi_surf->surface == ws) { -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ if(!dpy) -+ weston_log("no content in waltham_display\n"); -+ if(!dpy->compositor) -+ weston_log("no content in compositor object\n"); -+ if(!dpy->seat) -+ weston_log("no content in seat object\n"); -+ if(!dpy->application) -+ weston_log("no content in ivi-application object\n"); -+ -+ txs->wthp_ivi_surface = wthp_ivi_application_surface_create -+ (dpy->application, ivi_surf->id_surface, txs->wthp_surf); -+ weston_log("surface ID %d\n", ivi_surf->id_surface); -+ if(!txs->wthp_ivi_surface){ -+ weston_log("Failed to create txs->ivi_surf\n"); -+ } -+ } -+ } -+ free(pp_surface); -+ pp_surface = NULL; - } - - static struct weston_transmitter_surface * -@@ -350,39 +288,58 @@ transmitter_surface_push_to_remote(struct weston_surface *ws, - struct weston_transmitter_remote *remote, - struct wl_listener *stream_status) - { -+ struct weston_transmitter *txr = remote->transmitter; - struct weston_transmitter_surface *txs; -+ bool found = false; - -- if (transmitter_surface_get(ws)) { -- weston_log("Transmitter: surface %p already bound.\n", ws); -+ if (remote->status != WESTON_TRANSMITTER_CONNECTION_READY) -+ { - return NULL; - } - -- txs = zalloc(sizeof (*txs)); -- if (!txs) -- return NULL; -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == ws) { -+ found = true; -+ break; -+ } -+ } - -- txs->remote = remote; -- wl_signal_init(&txs->destroy_signal); -- wl_list_insert(&remote->surface_list, &txs->link); -+ if (!found) { -+ txs = NULL; -+ txs = zalloc(sizeof (*txs)); -+ if (!txs) -+ return NULL; - -- txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING; -- wl_signal_init(&txs->stream_status_signal); -- wl_signal_add(&txs->stream_status_signal, stream_status); -+ txs->remote = remote; -+ wl_signal_init(&txs->destroy_signal); -+ wl_list_insert(&remote->surface_list, &txs->link); - -- txs->surface = ws; -- txs->surface_destroy_listener.notify = transmitter_surface_destroyed; -- wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener); -+ txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING; -+ wl_signal_init(&txs->stream_status_signal); -+ if (stream_status) -+ wl_signal_add(&txs->stream_status_signal, stream_status); - -- txs->apply_state_listener.notify = transmitter_surface_apply_state; -- wl_signal_add(&ws->apply_state_signal, &txs->apply_state_listener); -+ txs->surface = ws; -+ txs->surface_destroy_listener.notify = transmitter_surface_destroyed; -+ wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener); - -- wl_list_init(&txs->sync_output_destroy_listener.link); -+ wl_list_init(&txs->sync_output_destroy_listener.link); - -- wl_list_init(&txs->frame_callback_list); -- wl_list_init(&txs->feedback_list); -+ wl_list_init(&txs->frame_callback_list); -+ wl_list_init(&txs->feedback_list); -+ -+ txs->lyt = weston_plugin_api_get(txr->compositor, -+ IVI_LAYOUT_API_NAME, sizeof(txs->lyt)); -+ } - - /* TODO: create the content stream connection... */ -- fake_stream_opening(txs); -+ if (!remote->display->compositor) -+ weston_log("remote->compositor is NULL\n"); -+ if (!txs->wthp_surf) { -+ weston_log("txs->wthp_surf is NULL\n"); -+ txs->wthp_surf = wthp_compositor_create_surface(remote->display->compositor); -+ transmitter_surface_set_ivi_id(txs); -+ } - - return txs; - } -@@ -393,17 +350,53 @@ transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs) - return txs->status; - } - --static int --conn_timer_handler(void *data) /* fake */ -+/* waltham */ -+/* The server advertises a global interface. -+ * We can store the ad for later and/or bind to it immediately -+ * if we want to. -+ * We also need to keep track of the globals we bind to, so that -+ * global_remove can be handled properly (not implemented). -+ */ -+static void -+registry_handle_global(struct wthp_registry *registry, -+ uint32_t name, -+ const char *interface, -+ uint32_t version) - { -- struct weston_transmitter_remote *remote = data; -+ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry); -+ -+ if (strcmp(interface, "wthp_compositor") == 0) { -+ assert(!dpy->compositor); -+ dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1); -+ /* has no events to handle */ -+ } else if (strcmp(interface, "wthp_blob_factory") == 0) { -+ assert(!dpy->blob_factory); -+ dpy->blob_factory = (struct wthp_blob_factory *)wthp_registry_bind(registry, name, interface, 1); -+ /* has no events to handle */ -+ } else if (strcmp(interface, "wthp_seat") == 0) { -+ assert(!dpy->seat); -+ dpy->seat = (struct wthp_seat *)wthp_registry_bind(registry, name, interface, 1); -+ wthp_seat_set_listener(dpy->seat, &seat_listener, dpy); -+ } else if (strcmp(interface, "wthp_ivi_application") == 0) { -+ assert(!dpy->application); -+ dpy->application = (struct wthp_ivi_application *)wthp_registry_bind(registry, name, interface, 1); -+ } -+} -+ -+/* notify connection ready */ -+static void -+conn_ready_notify(struct wl_listener *l, void *data) -+{ -+ struct weston_transmitter_remote *remote = -+ container_of(l, struct weston_transmitter_remote, -+ establish_listener); - struct weston_transmitter_output_info info = { - WL_OUTPUT_SUBPIXEL_NONE, - WL_OUTPUT_TRANSFORM_NORMAL, - 1, - 0, 0, - 300, 200, -- "fake", -+ strdup(remote->model), - { - WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, - 800, 600, -@@ -411,52 +404,303 @@ conn_timer_handler(void *data) /* fake */ - { NULL, NULL } - } - }; -- -- weston_log("Transmitter connected to %s.\n", remote->addr); -- remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -- wl_signal_emit(&remote->connection_status_signal, remote); -- -- wl_event_source_remove(remote->conn_timer); -- remote->conn_timer = NULL; -- -+ if(remote->width != 0) { -+ if(remote->height != 0) { -+ info.mode.width = remote->width; -+ info.mode.height = remote->height; -+ } -+ } - /* Outputs and seats are dynamic, do not guarantee they are all - * present when signalling connection status. - */ - transmitter_remote_create_output(remote, &info); - transmitter_remote_create_seat(remote); -+} -+ -+/* waltham */ -+/* The server removed a global. -+ * We should destroy everything we created through that global, -+ * and destroy the objects we created by binding to it. -+ * The identification happens by global's name, so we need to keep -+ * track what names we bound. -+ * (not implemented) -+ */ -+static void -+registry_handle_global_remove(struct wthp_registry *wthp_registry, -+ uint32_t name) -+{ -+ if (wthp_registry) -+ wthp_registry_free(wthp_registry); -+} -+ -+static const struct wthp_registry_listener registry_listener = { -+ registry_handle_global, -+ registry_handle_global_remove -+}; -+ -+static void -+connection_handle_data(struct watch *w, uint32_t events) -+{ -+ struct waltham_display *dpy = container_of(w, struct waltham_display, conn_watch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ int ret; -+ -+ -+ if (!dpy->running) { -+ weston_log("This server is not running yet. %s:%s\n", remote->addr, remote->port); -+ return; -+ } -+ -+ if (events & EPOLLERR) { -+ weston_log("Connection errored out.\n"); -+ dpy->running = false; -+ -+ return; -+ } -+ -+ if (events & EPOLLOUT) { -+ /* Flush out again. If the flush completes, stop -+ * polling for writable as everything has been written. -+ */ -+ ret = wth_connection_flush(dpy->connection); -+ } -+ -+ if (events & EPOLLIN) { -+ /* Do not ignore EPROTO */ -+ ret = wth_connection_read(dpy->connection); -+ if (ret < 0) { -+ weston_log("Connection read error %s:%s\n", remote->addr, remote->port); -+ perror("Connection read error\n"); -+ dpy->running = false; -+ perror("EPOLL_CTL_DEL\n"); -+ -+ return; -+ } -+ } -+ -+ if (events & EPOLLHUP) { -+ fprintf(stderr, "Connection hung up.\n"); -+ dpy->running = false; -+ -+ return; -+ } -+} -+ -+static void -+waltham_mainloop(int fd, uint32_t mask, void *data) -+{ -+ struct weston_transmitter_remote *remote = data; -+ struct watch *w; -+ int count; -+ int i; -+ int ret; -+ int running_display; -+ running_display = 0; -+ -+ struct waltham_display *dpy = remote->display; -+ w = &dpy->conn_watch; -+ if (!dpy) -+ goto not_running; -+ -+ if (!dpy->connection) -+ goto not_running; -+ -+ if (!dpy->running) -+ goto not_running; -+ -+ running_display++; -+ /* Dispatch queued events. */ -+ -+ ret = wth_connection_dispatch(dpy->connection); -+ if (ret < 0) -+ dpy->running = false; -+ if (!dpy->running) -+ goto not_running; -+ -+ /* Run any application idle tasks at this point. */ -+ /* (nothing to run so far) */ -+ -+ /* Flush out buffered requests. If the Waltham socket is -+ * full, poll it for writable too, and continue flushing then. -+ */ -+ ret = wth_connection_flush(dpy->connection); -+ -+ if (0 < running_display) { -+ /* Waltham events only read in the callback, not dispatched, -+ * if the Waltham socket signalled readable. If it signalled -+ * writable, flush more. See connection_handle_data(). -+ */ -+ w->cb(w, mask); -+ } -+ wl_event_source_remove(remote->source); -+ remote->source = wl_event_loop_add_fd(remote->transmitter->loop, -+ remote->display->conn_watch.fd, -+ WL_EVENT_READABLE, -+ waltham_mainloop, remote); -+ -+not_running: -+ ; -+} -+ -+/* A one-off asynchronous open-coded roundtrip handler. */ -+static void -+bling_done(struct wthp_callback *cb, uint32_t arg) -+{ -+ fprintf(stderr, "...sync done.\n"); -+ -+ wthp_callback_free(cb); -+} -+ -+static const struct wthp_callback_listener bling_listener = { -+ bling_done -+}; -+ -+static int -+waltham_client_init(struct waltham_display *dpy) -+{ -+ if (!dpy) -+ return -1; -+ /* -+ * get server_address from controller (adrress is set to weston.ini) -+ */ -+ dpy->connection = wth_connect_to_server(dpy->remote->addr, dpy->remote->port); -+ if(!dpy->connection) { -+ return -2; -+ } -+ else { -+ dpy->remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -+ wl_signal_emit(&dpy->remote->connection_status_signal, dpy->remote); -+ } -+ -+ dpy->conn_watch.display = dpy; -+ dpy->conn_watch.cb = connection_handle_data; -+ dpy->conn_watch.fd = wth_connection_get_fd(dpy->connection); -+ -+ dpy->display = wth_connection_get_display(dpy->connection); -+ /* wth_display_set_listener() is already done by waltham, as -+ * all the events are just control messaging. -+ */ -+ -+ /* Create a registry so that we will get advertisements of the -+ * interfaces implemented by the server. -+ */ -+ dpy->registry = wth_display_get_registry(dpy->display); -+ wthp_registry_set_listener(dpy->registry, ®istry_listener, dpy); -+ -+ /* Roundtrip ensures all globals' ads have been received. */ -+ if (wth_connection_roundtrip(dpy->connection) < 0) { -+ fprintf(stderr, "Roundtrip failed.\n"); -+ return -1; -+ } -+ -+ if (!dpy->compositor) { -+ fprintf(stderr, "Did not find wthp_compositor, quitting.\n"); -+ return -1; -+ } -+ -+ /* A one-off asynchronous roundtrip, just for fun. */ -+ fprintf(stderr, "sending wth_display.sync...\n"); -+ dpy->bling = wth_display_sync(dpy->display); -+ wthp_callback_set_listener(dpy->bling, &bling_listener, dpy); -+ -+ dpy->running = true; - - return 0; - } - --static struct weston_transmitter_remote * --transmitter_connect_to_remote(struct weston_transmitter *txr, -- const char *addr, -- struct wl_listener *status) -+static int -+establish_timer_handler(void *data) - { -- struct weston_transmitter_remote *remote; -- struct wl_event_loop *loop; -+ struct weston_transmitter_remote *remote = data; -+ int ret; - -- remote = zalloc(sizeof (*remote)); -- if (!remote) -- return NULL; -+ ret = waltham_client_init(remote->display); -+ if(ret == -2) { -+ wl_event_source_timer_update(remote->establish_timer, -+ ESTABLISH_CONNECTION_PERIOD); -+ return 0; -+ } -+ remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -+ wl_signal_emit(&remote->connection_status_signal, remote); -+ return 0; -+} - -- remote->transmitter = txr; -- wl_list_insert(&txr->remote_list, &remote->link); -- remote->addr = strdup(addr); -- remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -- wl_signal_init(&remote->connection_status_signal); -- wl_signal_add(&remote->connection_status_signal, status); -- wl_list_init(&remote->output_list); -- wl_list_init(&remote->surface_list); -- wl_list_init(&remote->seat_list); -+static void -+init_globals(struct waltham_display *dpy) -+{ -+ dpy->compositor = NULL; -+ dpy->blob_factory = NULL; -+ dpy->seat = NULL; -+ dpy->application = NULL; -+ dpy->pointer = NULL; -+ dpy->keyboard = NULL; -+ dpy->touch = NULL; -+} -+ -+static void -+disconnect_surface(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_surface *txs; -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ free(txs->wthp_ivi_surface); -+ free(txs->wthp_surf); -+ txs->wthp_ivi_surface = NULL; -+ txs->wthp_surf = NULL; -+ } -+} - -- /* XXX: actually start connecting */ -- weston_log("Transmitter connecting to %s...\n", addr); -- /* fake it with a one second timer */ -- loop = wl_display_get_event_loop(txr->compositor->wl_display); -- remote->conn_timer = wl_event_loop_add_timer(loop, conn_timer_handler, -- remote); -- wl_event_source_timer_update(remote->conn_timer, 1000); -+static int -+retry_timer_handler(void *data) -+{ -+ struct weston_transmitter_remote *remote = data; -+ struct waltham_display *dpy = remote->display; -+ -+ if(!dpy->running) -+ { -+ registry_handle_global_remove(dpy->registry, 1); -+ init_globals(dpy); -+ disconnect_surface(remote); -+ wl_event_source_timer_update(remote->establish_timer, -+ ESTABLISH_CONNECTION_PERIOD); -+ -+ return 0; -+ } -+ else -+ wl_event_source_timer_update(remote->retry_timer, -+ RETRY_CONNECTION_PERIOD); -+ return 0; -+} -+ -+static struct weston_transmitter_remote * -+transmitter_connect_to_remote(struct weston_transmitter *txr) -+{ -+ struct weston_transmitter_remote *remote; -+ struct wl_event_loop *loop_est, *loop_retry; -+ int ret; -+ -+ wl_list_for_each_reverse(remote, &txr->remote_list, link) { -+ /* XXX: actually start connecting */ -+ /* waltham */ -+ remote->display = zalloc(sizeof *remote->display); -+ if (!remote->display) -+ return NULL; -+ remote->display->remote = remote; -+ /* set connection establish timer */ -+ loop_est = wl_display_get_event_loop(txr->compositor->wl_display); -+ remote->establish_timer = -+ wl_event_loop_add_timer(loop_est, establish_timer_handler, remote); -+ wl_event_source_timer_update(remote->establish_timer, 1); -+ /* set connection retry timer */ -+ loop_retry = wl_display_get_event_loop(txr->compositor->wl_display); -+ remote->retry_timer = -+ wl_event_loop_add_timer(loop_retry, retry_timer_handler, remote); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter waltham connecting failed.\n"); -+ return NULL; -+ } -+ wl_signal_emit(&remote->conn_establish_signal, NULL); -+ } - - return remote; - } -@@ -481,10 +725,6 @@ transmitter_remote_destroy(struct weston_transmitter_remote *remote) - * the desctruction order between the shell and Transmitter is - * undefined. - */ -- weston_log("Transmitter disconnecting from %s.\n", remote->addr); -- -- if (remote->conn_timer) -- wl_event_source_remove(remote->conn_timer); - - if (!wl_list_empty(&remote->surface_list)) - weston_log("Transmitter warning: surfaces remain in %s.\n", -@@ -502,6 +742,8 @@ transmitter_remote_destroy(struct weston_transmitter_remote *remote) - free(remote->addr); - wl_list_remove(&remote->link); - -+ wl_event_source_remove(remote->source); -+ - free(remote); - } - -@@ -531,7 +773,6 @@ transmitter_compositor_destroyed(struct wl_listener *listener, void *data) - */ - wl_list_remove(&txr->remote_list); - -- weston_log("Transmitter terminating.\n"); - free(txr); - } - -@@ -553,6 +794,19 @@ transmitter_get(struct weston_compositor *compositor) - return txr; - } - -+static void -+transmitter_register_connection_status(struct weston_transmitter *txr, -+ struct wl_listener *connected_listener) -+{ -+ wl_signal_add(&txr->connected_signal, connected_listener); -+} -+ -+static struct weston_surface * -+transmitter_get_weston_surface(struct weston_transmitter_surface *txs) -+{ -+ return txs->surface; -+} -+ - static const struct weston_transmitter_api transmitter_api_impl = { - transmitter_get, - transmitter_connect_to_remote, -@@ -562,20 +816,12 @@ static const struct weston_transmitter_api transmitter_api_impl = { - transmitter_surface_get_stream_status, - transmitter_surface_destroy, - transmitter_surface_configure, -+ transmitter_surface_gather_state, -+ transmitter_register_connection_status, -+ transmitter_get_weston_surface, - }; - - static void --transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs, -- uint32_t ivi_id) --{ -- assert(txs->surface); -- if (!txs->surface) -- return; -- -- weston_log("%s(%p, %#x)\n", __func__, txs->surface, ivi_id); --} -- --static void - transmitter_surface_set_resize_callback( - struct weston_transmitter_surface *txs, - weston_transmitter_ivi_resize_handler_t cb, -@@ -586,10 +832,108 @@ transmitter_surface_set_resize_callback( - } - - static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = { -- transmitter_surface_set_ivi_id, - transmitter_surface_set_resize_callback, - }; - -+static int -+transmitter_create_remote(struct weston_transmitter *txr, -+ const char *model, -+ const char *addr, -+ const char *port, -+ const char *width, -+ const char *height) -+{ -+ struct weston_transmitter_remote *remote; -+ -+ remote = zalloc(sizeof (*remote)); -+ if (!remote) -+ return -1; -+ -+ remote->transmitter = txr; -+ wl_list_insert(&txr->remote_list, &remote->link); -+ remote->model = strdup(model); -+ remote->addr = strdup(addr); -+ remote->port = strdup(port); -+ remote->width = atoi(width); -+ remote->height = atoi(height); -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ wl_signal_init(&remote->connection_status_signal); -+ wl_list_init(&remote->output_list); -+ wl_list_init(&remote->surface_list); -+ wl_list_init(&remote->seat_list); -+ wl_signal_init(&remote->conn_establish_signal); -+ remote->establish_listener.notify = conn_ready_notify; -+ wl_signal_add(&remote->conn_establish_signal, &remote->establish_listener); -+ -+ return 0; -+} -+ -+static void -+transmitter_get_server_config(struct weston_transmitter *txr) -+{ -+ struct weston_config *config = wet_get_config(txr->compositor); -+ struct weston_config_section *section; -+ const char *name = NULL; -+ char *model = NULL; -+ char *addr = NULL; -+ char *port = NULL; -+ char *width = '0'; -+ char *height = '0'; -+ int ret; -+ -+ section = weston_config_get_section(config, "remote", NULL, NULL); -+ -+ while (weston_config_next_section(config, §ion, &name)) { -+ if (0 == strcmp(name, "remote-output")) { -+ if (0 != weston_config_section_get_string(section, "output-name", -+ &model, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "server-address", -+ &addr, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "port", -+ &port, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "width", -+ &width, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "height", -+ &height, 0)) -+ continue; -+ ret = transmitter_create_remote(txr, model, addr, -+ port, width, height); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter create_remote failed.\n"); -+ } -+ } -+ } -+} -+ -+static void -+transmitter_post_init(void *data) -+{ -+ struct weston_transmitter *txr = data; -+ struct weston_transmitter_remote *remote; -+ -+ if (!txr) { -+ weston_log("Transmitter disabled\n"); -+ } else { -+ transmitter_get_server_config(txr); -+ transmitter_connect_to_remote(txr); -+ -+ wl_list_for_each(remote, &txr->remote_list, link) { -+ remote->source = wl_event_loop_add_fd(txr->loop, -+ remote->display->conn_watch.fd, -+ WL_EVENT_READABLE, -+ waltham_mainloop, remote); -+ } -+ } -+} -+ - WL_EXPORT int - wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) - { -@@ -628,6 +972,9 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) - - weston_log("Transmitter initialized.\n"); - -+ txr->loop = wl_display_get_event_loop(compositor->wl_display); -+ wl_event_loop_add_idle(txr->loop, transmitter_post_init, txr); -+ - return 0; - - fail: -diff --git a/transmitter/plugin.h b/transmitter/plugin.h -index 710b543..48f49b8 100644 ---- a/transmitter/plugin.h -+++ b/transmitter/plugin.h -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2016 DENSO CORPORATION -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -32,33 +33,109 @@ - */ - - #include -+#include - - #include "compositor.h" - #include "transmitter_api.h" -+#include "ivi-shell/ivi-layout-export.h" -+ -+#include -+ -+ -+struct waltham_display; -+ -+enum wthp_seat_capability { -+ /** -+ * the seat has pointer devices -+ */ -+ WTHP_SEAT_CAPABILITY_POINTER = 1, -+ /** -+ * the seat has one or more keyboards -+ */ -+ WTHP_SEAT_CAPABILITY_KEYBOARD = 2, -+ /** -+ * the seat has touch devices -+ */ -+ WTHP_SEAT_CAPABILITY_TOUCH = 4, -+}; -+ -+/* epoll structure */ -+struct watch { -+ struct waltham_display *display; -+ int fd; -+ void (*cb)(struct watch *w, uint32_t events); -+}; -+ -+struct waltham_display { -+ struct wth_connection *connection; -+ struct watch conn_watch; -+ struct wth_display *display; -+ -+ bool running; -+ -+ struct wthp_registry *registry; -+ -+ struct wthp_callback *bling; -+ -+ struct wthp_compositor *compositor; -+ struct wthp_blob_factory *blob_factory; -+ struct wthp_seat *seat; -+ struct wthp_pointer *pointer; -+ struct wthp_keyboard *keyboard; -+ struct wthp_touch *touch; -+ struct wthp_ivi_application *application; -+ struct wtimer *fiddle_timer; -+ -+ struct weston_transmitter_remote *remote; -+ char *addr; -+ char *port; -+}; -+ -+/* a timerfd based timer */ -+struct wtimer { -+ struct watch watch; -+ void (*func)(struct wtimer *, void *); -+ void *data; -+}; - - struct weston_transmitter { - struct weston_compositor *compositor; - struct wl_listener compositor_destroy_listener; - - struct wl_list remote_list; /* transmitter_remote::link */ -+ -+ struct wl_listener stream_listener; -+ struct wl_signal connected_signal; -+ struct wl_event_loop *loop; - }; - - struct weston_transmitter_remote { - struct weston_transmitter *transmitter; - struct wl_list link; -- -+ char *model; - char *addr; -+ char *port; -+ int32_t width; -+ int32_t height; - - enum weston_transmitter_connection_status status; - struct wl_signal connection_status_signal; -+ struct wl_signal conn_establish_signal; - - struct wl_list output_list; /* weston_transmitter_output::link */ - struct wl_list surface_list; /* weston_transmitter_surface::link */ - struct wl_list seat_list; /* weston_transmitter_seat::link */ - -- struct wl_event_source *conn_timer; /* fake */ -+ struct wl_listener establish_listener; -+ -+ struct wl_event_source *establish_timer; /* for establish connection */ -+ struct wl_event_source *retry_timer; /* for retry connection */ -+ -+ struct waltham_display *display; /* waltham */ -+ struct wl_event_source *source; - }; - -+ - struct weston_transmitter_surface { - struct weston_transmitter_remote *remote; - struct wl_list link; /* weston_transmitter_remote::surface_list */ -@@ -69,7 +146,7 @@ struct weston_transmitter_surface { - - struct weston_surface *surface; - struct wl_listener surface_destroy_listener; -- struct wl_listener apply_state_listener; -+ const struct ivi_layout_interface *lyt; - - weston_transmitter_ivi_resize_handler_t resize_handler; - void *resize_handler_data; -@@ -77,13 +154,17 @@ struct weston_transmitter_surface { - struct weston_output *sync_output; - struct wl_listener sync_output_destroy_listener; - -- struct wl_event_source *map_timer; /* fake */ -- struct wl_event_source *frame_timer; /* fake */ -- - int32_t attach_dx; /**< wl_surface.attach(buffer, dx, dy) */ - int32_t attach_dy; /**< wl_surface.attach(buffer, dx, dy) */ - struct wl_list frame_callback_list; /* weston_frame_callback::link */ - struct wl_list feedback_list; /* weston_presentation_feedback::link */ -+ -+ /* waltham */ -+ struct wthp_surface *wthp_surf; -+ struct wthp_blob_factory *wthp_blob; -+ struct wthp_buffer *wthp_buf; -+ struct wthp_ivi_surface *wthp_ivi_surface; -+ struct wthp_ivi_application *wthp_ivi_application; - }; - - struct weston_transmitter_output_info { -@@ -103,12 +184,28 @@ struct weston_transmitter_output_info { - struct weston_transmitter_output { - struct weston_output base; - -+ struct { -+ bool draw_initial_frame; -+ struct wl_surface *surface; -+ struct wl_output *output; -+ struct wl_display *display; -+ int configure_width, configure_height; -+ bool wait_for_configure; -+ } parent; -+ - struct weston_transmitter_remote *remote; - struct wl_list link; /* weston_transmitter_remote::output_list */ -+ -+ struct frame *frame; -+ -+ struct wl_callback *frame_cb; -+ struct wl_listener frame_listener; -+ -+ bool from_frame_signal; - }; - - struct weston_transmitter_seat { -- struct weston_seat base; -+ struct weston_seat *base; - struct wl_list link; - - /* pointer */ -@@ -124,8 +221,28 @@ struct weston_transmitter_seat { - double pointer_phase; /* fake */ - - /* keyboard */ -+ struct weston_transmitter_surface *keyboard_focus; - - /* touch */ -+ struct weston_transmitter_surface *touch_focus; -+}; -+ -+struct ivi_layout_surface { -+ struct wl_list link; /* ivi_layout::surface_list */ -+ struct wl_signal property_changed; -+ int32_t update_count; -+ uint32_t id_surface; -+ -+ struct ivi_layout *layout; -+ struct weston_surface *surface; -+ -+ struct ivi_layout_surface_properties prop; -+ -+ struct { -+ struct ivi_layout_surface_properties prop; -+ } pending; -+ -+ struct wl_list view_list; /* ivi_layout_view::surf_link */ - }; - - void -@@ -203,5 +320,14 @@ int - transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, - struct weston_transmitter_surface *txs); - -+void -+seat_capabilities(struct wthp_seat *wthp_seat, -+ enum wthp_seat_capability caps); -+ -+static const struct wthp_seat_listener seat_listener = { -+ seat_capabilities, -+ NULL -+}; -+ - - #endif /* WESTON_TRANSMITTER_PLUGIN_H */ -diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h -index 95d82ec..b28f946 100644 ---- a/transmitter/transmitter_api.h -+++ b/transmitter/transmitter_api.h -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2016 DENSO CORPORATION -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -90,7 +91,6 @@ struct weston_transmitter_api { - * Connect to a remote server via Transmitter. - * - * \param txr The Transmitter context. -- * \param addr Address of the remote server. - * \param status Listener to inform of connection status changes. - * \return A handle to the remote connection, or NULL on failure. - * -@@ -102,12 +102,9 @@ struct weston_transmitter_api { - * returned by this function. Use remote_get_status() to fetch the - * current status. - * -- * The address argument is a string in the form "host:port". - */ - struct weston_transmitter_remote * -- (*connect_to_remote)(struct weston_transmitter *txr, -- const char *addr, -- struct wl_listener *status); -+ (*connect_to_remote)(struct weston_transmitter *txr); - - /** - * Retrieve the connection status. -@@ -191,6 +188,25 @@ struct weston_transmitter_api { - void - (*surface_configure)(struct weston_transmitter_surface *txs, - int32_t dx, int32_t dy); -+ -+ void -+ (*surface_gather_state)(struct weston_transmitter_surface *txs); -+ -+ /** Notify that surface is connected to receiver -+ * -+ * \param txr The Transmitter context. -+ * \param connected_listener Listener for connected_signal. -+ */ -+ void -+ (*register_connection_status)(struct weston_transmitter *txr, -+ struct wl_listener *connected_listener); -+ -+ /** get weston_surface from weston_transmitter_surface -+ * -+ * \param txs The Transmitter surface. -+ */ -+ struct weston_surface * -+ (*get_weston_surface)(struct weston_transmitter_surface *txs); - }; - - static inline const struct weston_transmitter_api * -diff --git a/transmitter/weston.ini.transmitter b/transmitter/weston.ini.transmitter -new file mode 100644 -index 0000000..1aff0b2 ---- /dev/null -+++ b/transmitter/weston.ini.transmitter -@@ -0,0 +1,21 @@ -+[core] -+shell=ivi-shell.so -+modules=transmitter.so -+ -+[ivi-shell] -+ivi-module=ivi-controller.so -+ivi-input-module=ivi-input-controller.so -+ -+[remote-output] -+output-name=transmitter_1 -+server-address=192.168.2.11 -+port=34400 -+width=1920 -+height=1080 -+ -+[remote-output] -+output-name=transmitter_2 -+server-address=192.168.2.12 -+port=34400 -+width=1920 -+height=1080 --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0021-transmitter-add-output-type-for-waltham-output.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0021-transmitter-add-output-type-for-waltham-output.patch deleted file mode 100644 index 63182581f..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0021-transmitter-add-output-type-for-waltham-output.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 329b7a0a897af8142871e5c44e0f9bc4b55f2bc6 Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Thu, 12 Oct 2017 16:13:58 +0900 -Subject: [PATCH 2/5] transmitter: add output type for waltham output - -Transmitter creates waltham output -This makes weston has several outputs -Since each backends have each output several outputs -makes invalid member access -To avoid it output type should be identified - -Signed-off-by: Wataru Mizuno ---- - transmitter/output.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/transmitter/output.c b/transmitter/output.c -index a3f8ed1..19a3273 100644 ---- a/transmitter/output.c -+++ b/transmitter/output.c -@@ -239,7 +239,7 @@ transmitter_output_enable(struct weston_output *base) - { - struct weston_transmitter_output *output = to_transmitter_output(base); - -- -+ output->base.output_type = OUTPUT_WALTHAM; - output->base.assign_planes = NULL; - output->base.set_backlight = NULL; - output->base.set_dpms = NULL; --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0022-transmitter-did-code-cleaning.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0022-transmitter-did-code-cleaning.patch deleted file mode 100644 index bcdd6cbb6..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0022-transmitter-did-code-cleaning.patch +++ /dev/null @@ -1,708 +0,0 @@ -From b93057e8f4f05b33c5eb2c6f06dae3228dbb409e Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Tue, 10 Apr 2018 19:36:02 +0900 -Subject: [PATCH 1/2] transmitter: did code clean -Remove unused variables and - functions -Replace container_of to wl_container_of - -Signed-off-by: Wataru Mizuno ---- - transmitter/input.c | 45 ++++-------- - transmitter/output.c | 37 ++++------ - transmitter/plugin.c | 156 +++++++++++++++--------------------------- - transmitter/plugin.h | 3 +- - transmitter/transmitter_api.h | 3 +- - 5 files changed, 87 insertions(+), 157 deletions(-) - -diff --git a/transmitter/input.c b/transmitter/input.c -index eeb7452..6797b6e 100644 ---- a/transmitter/input.c -+++ b/transmitter/input.c -@@ -1,6 +1,5 @@ - /* -- * Copyright (C) 2016 DENSO CORPORATION -- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -24,8 +23,6 @@ - * SOFTWARE. - */ - --#include "config.h" -- - #include - #include - #include -@@ -34,7 +31,6 @@ - #include - - #include "compositor.h" --#include "helpers.h" - - #include "plugin.h" - #include "transmitter_api.h" -@@ -810,8 +806,7 @@ pointer_handle_enter(struct wthp_pointer *wthp_pointer, - struct weston_transmitter_seat *seat; - struct weston_transmitter_surface *txs; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) - { -@@ -836,8 +831,7 @@ pointer_handle_leave(struct wthp_pointer *wthp_pointer, - struct weston_transmitter_seat *seat; - struct weston_transmitter_surface *txs; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) - { -@@ -859,8 +853,7 @@ pointer_handle_motion(struct wthp_pointer *wthp_pointer, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_pointer_motion(seat, time, - surface_x, -@@ -880,8 +873,7 @@ pointer_handle_button(struct wthp_pointer *wthp_pointer, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_pointer_button(seat, serial, - time, button, -@@ -899,8 +891,7 @@ pointer_handle_axis(struct wthp_pointer *wthp_pointer, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_pointer_axis(seat, time, - axis, value); -@@ -974,8 +965,7 @@ keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard, - wl_key->alloc = keys->alloc; - wl_key->data = keys->data; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) - { -@@ -999,8 +989,7 @@ keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard, - struct weston_transmitter_seat *seat; - struct weston_transmitter_surface *txs; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) - { -@@ -1023,8 +1012,7 @@ keyboard_handle_key(struct wthp_keyboard *wthp_keyboard, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_keyboard_key(seat, serial, time, key, state); - } -@@ -1073,8 +1061,7 @@ touch_handle_down (struct wthp_touch * wthp_touch, - struct weston_transmitter_seat *seat; - struct weston_transmitter_surface *txs; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) - { -@@ -1097,8 +1084,7 @@ touch_handle_up (struct wthp_touch * wthp_touch, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_touch_up(seat, serial, time, id); - } -@@ -1116,8 +1102,7 @@ touch_handle_motion (struct wthp_touch * wthp_touch, - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_touch_motion(seat, time, id, x, y); - } -@@ -1132,8 +1117,7 @@ touch_handle_frame (struct wthp_touch * wthp_touch) - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_touch_frame(seat); - } -@@ -1147,8 +1131,7 @@ touch_handle_cancel (struct wthp_touch * wthp_touch) - struct wl_list *seat_list = &remote->seat_list; - struct weston_transmitter_seat *seat; - -- seat = container_of(seat_list->next, -- struct weston_transmitter_seat, link); -+ seat = wl_container_of(seat_list->next, seat, link); - - transmitter_seat_touch_cancel(seat); - } -diff --git a/transmitter/output.c b/transmitter/output.c -index 19a3273..003056f 100644 ---- a/transmitter/output.c -+++ b/transmitter/output.c -@@ -1,6 +1,5 @@ - /* -- * Copyright (C) 2016 DENSO CORPORATION -- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -24,14 +23,11 @@ - * SOFTWARE. - */ - --#include "config.h" -- - #include - #include - #include - - #include "compositor.h" --#include "helpers.h" - - #include "plugin.h" - #include "transmitter_api.h" -@@ -63,12 +59,6 @@ - * exclusive with weston_compositor_add_output(). - */ - --static inline struct weston_transmitter_output * --to_transmitter_output(struct weston_output *base) --{ -- return container_of(base, struct weston_transmitter_output, base); --} -- - static char * - make_model(struct weston_transmitter_remote *remote, int name) - { -@@ -115,7 +105,7 @@ free_mode_list(struct wl_list *mode_list) - struct weston_mode *mode; - - while (!wl_list_empty(mode_list)) { -- mode = container_of(mode_list->next, struct weston_mode, link); -+ mode = wl_container_of(mode_list->next, mode, link); - - wl_list_remove(&mode->link); - free(mode); -@@ -139,7 +129,7 @@ transmitter_output_destroy(struct weston_transmitter_output *output) - static void - transmitter_output_destroy_(struct weston_output *base) - { -- struct weston_transmitter_output *output = to_transmitter_output(base); -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); - - transmitter_output_destroy(output); - } -@@ -149,7 +139,7 @@ static void - transmitter_start_repaint_loop(struct weston_output *base) - { - struct timespec ts; -- struct weston_transmitter_output *output = to_transmitter_output(base); -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); - - weston_compositor_read_presentation_clock(output->base.compositor, &ts); - weston_output_finish_frame(&output->base, &ts, 0); -@@ -159,8 +149,8 @@ static int - transmitter_check_output(struct weston_transmitter_surface *txs, - struct weston_compositor *compositor) - { -- struct weston_output *def_output = container_of(compositor->output_list.next, -- struct weston_output, link); -+ struct weston_output *def_output = wl_container_of(compositor->output_list.next, -+ def_output, link); - struct weston_view *view; - - wl_list_for_each_reverse(view, &compositor->view_list, link) { -@@ -177,7 +167,7 @@ static int - transmitter_output_repaint(struct weston_output *base, - pixman_region32_t *damage) - { -- struct weston_transmitter_output* output = to_transmitter_output(base); -+ struct weston_transmitter_output* output = wl_container_of(base, output, base); - struct weston_transmitter_remote* remote = output->remote; - struct weston_transmitter* txr = remote->transmitter; - struct weston_transmitter_api* transmitter_api = -@@ -201,6 +191,9 @@ transmitter_output_repaint(struct weston_output *base, - if (wl_list_empty(&compositor->view_list)) - goto out; - -+ if (remote->status == WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) -+ goto out; -+ - wl_list_for_each_reverse(view, &compositor->view_list, link) { - bool found_surface = false; - if (view->output == &output->base) { -@@ -237,9 +230,8 @@ out: - static void - transmitter_output_enable(struct weston_output *base) - { -- struct weston_transmitter_output *output = to_transmitter_output(base); -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); - -- output->base.output_type = OUTPUT_WALTHAM; - output->base.assign_planes = NULL; - output->base.set_backlight = NULL; - output->base.set_dpms = NULL; -@@ -252,8 +244,7 @@ transmitter_output_frame_handler(struct wl_listener *listener, void *data) - struct weston_transmitter_output *output; - int ret; - -- output = container_of(listener, struct weston_transmitter_output, -- frame_listener); -+ output = wl_container_of(listener, output, frame_listener); - output->from_frame_signal = true; - - ret = transmitter_output_repaint(&output->base, NULL); -@@ -324,8 +315,8 @@ transmitter_remote_create_output(struct weston_transmitter_remote *remote, - weston_output_enable(&output->base); - - output->frame_listener.notify = transmitter_output_frame_handler; -- def_output = container_of(txr->compositor->output_list.next, -- struct weston_output, link); -+ def_output = wl_container_of(txr->compositor->output_list.next, -+ def_output, link); - wl_signal_add(&def_output->frame_signal, &output->frame_listener); - output->from_frame_signal = false; - -diff --git a/transmitter/plugin.c b/transmitter/plugin.c -index 1ebd1ef..1f00f33 100644 ---- a/transmitter/plugin.c -+++ b/transmitter/plugin.c -@@ -1,6 +1,5 @@ - /* -- * Copyright (C) 2016 DENSO CORPORATION -- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -@@ -24,16 +23,12 @@ - * SOFTWARE. - */ - --#include "config.h" -- - #include - #include - #include - #include - - #include "compositor.h" --#include "helpers.h" --#include "timespec-util.h" - - #include "compositor/weston.h" - #include "plugin.h" -@@ -113,10 +108,13 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs) - { - struct weston_transmitter_remote *remote = txs->remote; - struct waltham_display *dpy = remote->display; -+ int ret; - - if(!dpy->running) { - if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) { - remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED; -+ wth_connection_destroy(remote->display->connection); -+ wl_event_source_remove(remote->source); - wl_event_source_timer_update(remote->retry_timer, 1); - } - } -@@ -127,43 +125,32 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs) - /* waltham */ - struct weston_surface *surf = txs->surface; - struct weston_compositor *comp = surf->compositor; -- int32_t width = 100; -- int32_t height = 100; -- int32_t stride; -- int ret = 0; -- void *pixels; -- --// stride = surf->width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); -+ int32_t stride, data_sz, width, height; -+ void *data; -+ -+ width = 1; -+ height = 1; - stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); --// weston_log("width %d\n", surf->width); --// weston_log("height %d\n", surf->height); --// weston_log("stride %d\n", stride); -- pixels = malloc(stride * height); - -- ret = weston_surface_copy_content(surf, pixels, -- (stride * height), 0, 0, -- width, height); -- if(ret < 0) -- fprintf(stderr, "failed to get surface content\n"); -- -+ data = malloc(stride * height); -+ data_sz = stride * height; -+ - /* fake sending buffer */ - txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory, -- (stride * height), -- pixels, -- width, -- height, -+ data_sz, -+ data, -+ surf->width, -+ surf->height, - stride, - PIXMAN_FORMAT_BPP(comp->read_format)); - - wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs); - - wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy); -- //wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); -- wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, width, height); -+ wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); - wthp_surface_commit(txs->wthp_surf); -- -- wth_connection_flush(remote->display->connection); - -+ wth_connection_flush(remote->display->connection); - txs->attach_dx = 0; - txs->attach_dy = 0; - } -@@ -216,8 +203,7 @@ static void - transmitter_surface_destroyed(struct wl_listener *listener, void *data) - { - struct weston_transmitter_surface *txs = -- container_of(listener, struct weston_transmitter_surface, -- surface_destroy_listener); -+ wl_container_of(listener, txs, surface_destroy_listener); - - assert(data == txs->surface); - -@@ -229,8 +215,7 @@ sync_output_destroy_handler(struct wl_listener *listener, void *data) - { - struct weston_transmitter_surface *txs; - -- txs = container_of(listener, struct weston_transmitter_surface, -- sync_output_destroy_listener); -+ txs = wl_container_of(listener, txs, sync_output_destroy_listener); - - wl_list_remove(&txs->sync_output_destroy_listener.link); - wl_list_init(&txs->sync_output_destroy_listener.link); -@@ -364,7 +349,7 @@ registry_handle_global(struct wthp_registry *registry, - uint32_t version) - { - struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry); -- -+ - if (strcmp(interface, "wthp_compositor") == 0) { - assert(!dpy->compositor); - dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1); -@@ -388,8 +373,7 @@ static void - conn_ready_notify(struct wl_listener *l, void *data) - { - struct weston_transmitter_remote *remote = -- container_of(l, struct weston_transmitter_remote, -- establish_listener); -+ wl_container_of(l, remote, establish_listener); - struct weston_transmitter_output_info info = { - WL_OUTPUT_SUBPIXEL_NONE, - WL_OUTPUT_TRANSFORM_NORMAL, -@@ -441,7 +425,7 @@ static const struct wthp_registry_listener registry_listener = { - static void - connection_handle_data(struct watch *w, uint32_t events) - { -- struct waltham_display *dpy = container_of(w, struct waltham_display, conn_watch); -+ struct waltham_display *dpy = wl_container_of(w, dpy, conn_watch); - struct weston_transmitter_remote *remote = dpy->remote; - int ret; - -@@ -454,7 +438,7 @@ connection_handle_data(struct watch *w, uint32_t events) - if (events & EPOLLERR) { - weston_log("Connection errored out.\n"); - dpy->running = false; -- -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; - return; - } - -@@ -468,10 +452,12 @@ connection_handle_data(struct watch *w, uint32_t events) - if (events & EPOLLIN) { - /* Do not ignore EPROTO */ - ret = wth_connection_read(dpy->connection); -+ - if (ret < 0) { - weston_log("Connection read error %s:%s\n", remote->addr, remote->port); - perror("Connection read error\n"); - dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; - perror("EPOLL_CTL_DEL\n"); - - return; -@@ -479,8 +465,9 @@ connection_handle_data(struct watch *w, uint32_t events) - } - - if (events & EPOLLHUP) { -- fprintf(stderr, "Connection hung up.\n"); -+ weston_log("Connection hung up.\n"); - dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; - - return; - } -@@ -491,8 +478,6 @@ waltham_mainloop(int fd, uint32_t mask, void *data) - { - struct weston_transmitter_remote *remote = data; - struct watch *w; -- int count; -- int i; - int ret; - int running_display; - running_display = 0; -@@ -503,17 +488,18 @@ waltham_mainloop(int fd, uint32_t mask, void *data) - goto not_running; - - if (!dpy->connection) -- goto not_running; -- -+ dpy->running = false; -+ - if (!dpy->running) - goto not_running; - - running_display++; - /* Dispatch queued events. */ -- - ret = wth_connection_dispatch(dpy->connection); -- if (ret < 0) -+ if (ret < 0) { - dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ } - if (!dpy->running) - goto not_running; - -@@ -532,29 +518,11 @@ waltham_mainloop(int fd, uint32_t mask, void *data) - */ - w->cb(w, mask); - } -- wl_event_source_remove(remote->source); -- remote->source = wl_event_loop_add_fd(remote->transmitter->loop, -- remote->display->conn_watch.fd, -- WL_EVENT_READABLE, -- waltham_mainloop, remote); - - not_running: - ; - } - --/* A one-off asynchronous open-coded roundtrip handler. */ --static void --bling_done(struct wthp_callback *cb, uint32_t arg) --{ -- fprintf(stderr, "...sync done.\n"); -- -- wthp_callback_free(cb); --} -- --static const struct wthp_callback_listener bling_listener = { -- bling_done --}; -- - static int - waltham_client_init(struct waltham_display *dpy) - { -@@ -575,6 +543,10 @@ waltham_client_init(struct waltham_display *dpy) - dpy->conn_watch.display = dpy; - dpy->conn_watch.cb = connection_handle_data; - dpy->conn_watch.fd = wth_connection_get_fd(dpy->connection); -+ dpy->remote->source = wl_event_loop_add_fd(dpy->remote->transmitter->loop, -+ dpy->conn_watch.fd, -+ WL_EVENT_READABLE, -+ waltham_mainloop, dpy->remote); - - dpy->display = wth_connection_get_display(dpy->connection); - /* wth_display_set_listener() is already done by waltham, as -@@ -589,19 +561,17 @@ waltham_client_init(struct waltham_display *dpy) - - /* Roundtrip ensures all globals' ads have been received. */ - if (wth_connection_roundtrip(dpy->connection) < 0) { -- fprintf(stderr, "Roundtrip failed.\n"); -+ weston_log("Roundtrip failed.\n"); - return -1; - } - - if (!dpy->compositor) { -- fprintf(stderr, "Did not find wthp_compositor, quitting.\n"); -+ weston_log("Did not find wthp_compositor, quitting.\n"); - return -1; - } - - /* A one-off asynchronous roundtrip, just for fun. */ -- fprintf(stderr, "sending wth_display.sync...\n"); -- dpy->bling = wth_display_sync(dpy->display); -- wthp_callback_set_listener(dpy->bling, &bling_listener, dpy); -+ weston_log("sending wth_display.sync...\n"); - - dpy->running = true; - -@@ -644,8 +614,8 @@ disconnect_surface(struct weston_transmitter_remote *remote) - wl_list_for_each(txs, &remote->surface_list, link) - { - free(txs->wthp_ivi_surface); -- free(txs->wthp_surf); - txs->wthp_ivi_surface = NULL; -+ free(txs->wthp_surf); - txs->wthp_surf = NULL; - } - } -@@ -754,8 +724,7 @@ transmitter_compositor_destroyed(struct wl_listener *listener, void *data) - struct weston_transmitter_remote *remote; - struct weston_transmitter_surface *txs; - struct weston_transmitter *txr = -- container_of(listener, struct weston_transmitter, -- compositor_destroy_listener); -+ wl_container_of(listener, txr, compositor_destroy_listener); - - assert(data == txr->compositor); - -@@ -787,8 +756,7 @@ transmitter_get(struct weston_compositor *compositor) - if (!listener) - return NULL; - -- txr = container_of(listener, struct weston_transmitter, -- compositor_destroy_listener); -+ txr = wl_container_of(listener, txr, compositor_destroy_listener); - assert(compositor == txr->compositor); - - return txr; -@@ -868,9 +836,18 @@ transmitter_create_remote(struct weston_transmitter *txr, - return 0; - } - -+struct wet_compositor { -+ struct weston_config *config; -+ struct wet_output_config *parsed_options; -+ struct wl_listener pending_output_listener; -+ bool drm_use_current_mode; -+}; -+ - static void - transmitter_get_server_config(struct weston_transmitter *txr) - { -+ struct wet_compositor *compositor = -+ (struct wet_compositor *)weston_compositor_get_user_data(txr->compositor); - struct weston_config *config = wet_get_config(txr->compositor); - struct weston_config_section *section; - const char *name = NULL; -@@ -913,27 +890,6 @@ transmitter_get_server_config(struct weston_transmitter *txr) - } - } - --static void --transmitter_post_init(void *data) --{ -- struct weston_transmitter *txr = data; -- struct weston_transmitter_remote *remote; -- -- if (!txr) { -- weston_log("Transmitter disabled\n"); -- } else { -- transmitter_get_server_config(txr); -- transmitter_connect_to_remote(txr); -- -- wl_list_for_each(remote, &txr->remote_list, link) { -- remote->source = wl_event_loop_add_fd(txr->loop, -- remote->display->conn_watch.fd, -- WL_EVENT_READABLE, -- waltham_mainloop, remote); -- } -- } --} -- - WL_EXPORT int - wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) - { -@@ -941,9 +897,10 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) - int ret; - - txr = zalloc(sizeof *txr); -- if (!txr) -+ if (!txr){ -+ weston_log("Transmitter disabled\n"); - return -1; -- -+ } - wl_list_init(&txr->remote_list); - - txr->compositor = compositor; -@@ -973,7 +930,8 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) - weston_log("Transmitter initialized.\n"); - - txr->loop = wl_display_get_event_loop(compositor->wl_display); -- wl_event_loop_add_idle(txr->loop, transmitter_post_init, txr); -+ transmitter_get_server_config(txr); -+ transmitter_connect_to_remote(txr); - - return 0; - -diff --git a/transmitter/plugin.h b/transmitter/plugin.h -index 48f49b8..116c1f6 100644 ---- a/transmitter/plugin.h -+++ b/transmitter/plugin.h -@@ -1,6 +1,5 @@ - /* -- * Copyright (C) 2016 DENSO CORPORATION -- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the -diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h -index b28f946..4a660a0 100644 ---- a/transmitter/transmitter_api.h -+++ b/transmitter/transmitter_api.h -@@ -1,6 +1,5 @@ - /* -- * Copyright (C) 2016 DENSO CORPORATION -- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0024-transmitter-introduce-waltham-renderer.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0024-transmitter-introduce-waltham-renderer.patch deleted file mode 100644 index a328bde13..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0024-transmitter-introduce-waltham-renderer.patch +++ /dev/null @@ -1,803 +0,0 @@ -From 0db59bf629def81fe9925fa435ec845e2069dd4b Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Wed, 11 Apr 2018 12:19:58 +0900 -Subject: [PATCH] transmitter: introduce waltham-renderer - -The waltham-renderer creates and sends buffer for remote site. -This is using gst-recorder APIs. - -Signed-off-by: Wataru Mizuno ---- - Makefile.am | 12 +++ - transmitter/README | 86 +++++++++++---------- - transmitter/input.c | 2 +- - transmitter/output.c | 104 ++++++++++++++------------ - transmitter/plugin.c | 45 ++++++----- - transmitter/plugin.h | 6 +- - transmitter/transmitter_api.h | 9 +++ - transmitter/waltham-renderer.c | 166 +++++++++++++++++++++++++++++++++++++++++ - transmitter/waltham-renderer.h | 33 ++++++++ - 9 files changed, 347 insertions(+), 116 deletions(-) - create mode 100644 transmitter/waltham-renderer.c - create mode 100644 transmitter/waltham-renderer.h - -diff --git a/Makefile.am b/Makefile.am -index 2cb1920..0af66d6 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -526,6 +526,18 @@ transmitter_la_SOURCES = \ - shared/timespec-util.h \ - shared/zalloc.h \ - src/compositor.h -+ -+module_LTLIBRARIES += waltham-renderer.la -+waltham_renderer_la_LDFLAGS = -module -avoid-version -+waltham_renderer_la_CFLAGS = \ -+ $(COMPOSITOR_CFLAGS) \ -+ $(AM_CFLAGS) \ -+ $(WALTHAM_CFLAGS) -+waltham_renderer_la_LIBADD = $(COMPOSITOR_LIBS) \ -+ -lwaltham -+waltham_renderer_la_SOURCES = \ -+ transmitter/waltham-renderer.c \ -+ transmitter/waltham-renderer.h - endif - - noinst_PROGRAMS += spring-tool -diff --git a/transmitter/README b/transmitter/README -index af80574..345142d 100644 ---- a/transmitter/README -+++ b/transmitter/README -@@ -1,4 +1,4 @@ --Transmitter plugin -+Transmitter plugin - - The current implementation of Transmitter is a stub which interfaces to - other Weston parts appropriately, but all networking is just a mockup. -@@ -15,8 +15,8 @@ plugin. - - How to write weston.ini - ======================= --To load transmitter plugin to weston, add 'transmitter.so' to the 'modules' --key under '[core]', and make sure the 'shell' is 'ivi-shell.so'. -+To load transmitter plugin to weston, add 'transmitter.so' to the 'modules' -+key under '[core]', and make sure the 'shell' is 'ivi-shell.so'. - - The destination of remoting is configured in weston.ini. - Add output name, server address, port number, output's width and height key -@@ -27,57 +27,66 @@ In details, see 'weston.ini.transmitter'. - - How to test - =========== --You can use server side test application in waltham repository. -+You can use server side test application in waltham-server directory. - - If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can - see the log like this: - -- [06:12:41.238] Loading module '/usr/lib64/weston/ivi-shell.so' -- [06:12:41.245] launching '/usr/libexec/weston-keyboard' -- [06:12:41.247] Loading module '/usr/lib64/weston/ivi-controller.so' -- [06:12:41.252] Loading module '/usr/lib64/weston/ivi-input-controller.so' -- [06:12:41.253] ivi-input-controller module loaded successfully! -- [06:12:41.255] Loading module '/usr/lib64/weston/transmitter.so' -- [06:12:41.260] Registered plugin API 'transmitter_v1' of size 88 -- [06:12:41.260] Registered plugin API 'transmitter_ivi_v1' of size 16 -- [06:12:41.260] Transmitter initialized. -- [06:12:41.260] ivi-layout: Transmitter enabled. -- [06:12:41.260] Transmitter weston_seat 0x14f8010 -- [06:12:41.260] Transmitter created pointer=0x139a440 for seat 0x14f8010 -- [06:12:41.261] Transmitter created keyboard=0x14f8160 for seat 0x14f8010 -- [06:12:41.261] Transmitter created touch=0x1508750 for seat 0x14f8010 -+ [13:24:08.345] Loading module '/usr/lib64/weston/transmitter.so' -+ [13:24:08.345] Registered plugin API 'transmitter_v1' of size 88 -+ [13:24:08.345] Registered plugin API 'transmitter_ivi_v1' of size 16 -+ [13:24:08.345] Transmitter initialized. -+ [13:24:08.345] Loading module '/usr/lib64/libweston-2/waltham-renderer.so' -+ [13:24:08.352] gst-setting are :--> -+ [13:24:08.352] ip = 192.168.2.52 -+ [13:24:08.352] port = 34400 -+ [13:24:08.352] bitrate = 3000000 -+ [13:24:08.352] crop = 384 x 368 -+ [13:24:08.352] width = 1920 -+ [13:24:08.352] width = 1080 -+ [13:24:08.531] open media device: platform:fe960000.vsp (fe960000.vsp) -+ [13:24:08.532] input pad setup ('fe960000.vsp rpf.0 input':'/dev/video0') -+ [13:24:08.533] output pad setup (fe960000.vsp wpf.0 output:/dev/video5) -+ [13:24:08.533] vsp-device '/dev/media0' created -+ [13:24:08.533] gst_recorder_create (1920x1080) crop 384x368 at 0,0 -+ [13:24:08.533] gst_pipeline: starting: appsrc name=src ! omxh264enc target-bitrate=3000000 control-rate=2 no-copy=k -+ [13:24:08.582] goot 1 pools -+ [13:24:08.583] pool settings size 211968, min 5, max 5 -+ [13:24:08.583] gst_recorder_create done -+ [13:24:08.583] [gst recorder] transmitter-192.168.2.52:34400-1: recorder initialized -+ [13:24:08.583] Transmitter weston_seat 0x15424630 -+ [13:24:08.583] Transmitter created pointer=0x15625df0 for seat 0x15424630 -+ [13:24:08.583] Transmitter created keyboard=0x154247c0 for seat 0x15424630 -+ [13:24:08.583] Transmitter created touch=0x15625f10 for seat 0x15424630 - - The connection is established, you can see following debug messages: - -- root@gr-mrb-64:~# debug: wth_connection_insert_new_object: new object id: 1 -+ debug: wth_connection_insert_new_object: new object id: 1 - debug: wth_connection_insert_new_object: new object id: 2 -- 2017-07-19T06:14:31Z 00001000030000000100000002000000 wth_display_get_registry -+ 2018-01-09T13:24:22Z 00001000030000000100000002000000 wth_display_get_registry - debug: wth_connection_insert_new_object: new object id: 3 -- 2017-07-19T06:14:31Z 00001000020000000100000003000000 wth_display_sync -- debug: Message received on conn 0x1560340: (9) 40 bytes -+ 2018-01-09T13:24:22Z 00001000020000000100000003000000 wth_display_sync -+ debug: Message received on conn 0x15572730: (9) 40 bytes - debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. - debug: wth_connection_insert_new_object: new object id: 4 -- 2017-07-19T06:14:31Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthp_registry_bind -- debug: Message received on conn 0x1560340: (9) 44 bytes -- debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -- debug: wth_connection_insert_new_object: new object id: 5 -- 2017-07-19T06:14:31Z 000030000800000002000000010000000500000012000000777468705f626c6f625f666163746f72790001000000 wthp_registry_bind -- debug: Message received on conn 0x1560340: (9) 48 bytes -+ 2018-01-09T13:24:22Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthpd -+ debug: Message received on conn 0x15572730: (9) 48 bytes - debug: wthp_registry_send_global(2, 1, [variable type const char *], 1) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 5 -+ 2018-01-09T13:24:22Z 000034000800000002000000010000000500000015000000777468705f6976695f6170706c69636174696f6e00010d -+ debug: Message received on conn 0x15572730: (9) 44 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. - debug: wth_connection_insert_new_object: new object id: 6 -- 2017-07-19T06:14:31Z 000034000800000002000000010000000600000015000000777468705f6976695f6170706c69636174696f6e0001000000 wthp_registry_bind -- debug: Message received on conn 0x1560340: (11) 16 bytes -- debug: wthp_callback_send_done(3, 0) (opcode 11) called. -- sending wth_display.sync... -+ 2018-01-09T13:24:22Z 000030000800000002000000010000000600000012000000777468705f626c6f625f666163746f72790001000000 d -+ debug: Message received on conn 0x15572730: (9) 36 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. - debug: wth_connection_insert_new_object: new object id: 7 -- 2017-07-19T06:14:31Z 00001000020000000100000007000000 wth_display_sync -- debug: Message received on conn 0x1560340: (11) 16 bytes -- debug: wthp_callback_send_done(7, 0) (opcode 11) called. -- ...sync done. -+ 2018-01-09T13:24:22Z 00002800080000000200000001000000070000000a000000777468705f736561740001000000 wthp_registry_bid -+ debug: Message received on conn 0x15572730: (11) 16 bytes -+ debug: wthp_callback_send_done(3, 0) (opcode 11) called. - - Start remoting : - - Start an IVI application. --- Put surface on backend output - - Put surface on transmitter output - - Weston log will indicate remoting has started: -@@ -85,5 +94,4 @@ Weston log will indicate remoting has started: - [13:18:24.572] HMI transmitting surface 0x1c3dad0, ivi-id 0x9ff6 - [13:18:24.572] Transmitter: update surface 0x1c3dad0 (0, 0), 0 cb - [13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6) --[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 -- -+[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 -\ No newline at end of file -diff --git a/transmitter/input.c b/transmitter/input.c -index 6797b6e..e00546b 100644 ---- a/transmitter/input.c -+++ b/transmitter/input.c -@@ -964,7 +964,7 @@ keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard, - wl_key->size = keys->size; - wl_key->alloc = keys->alloc; - wl_key->data = keys->data; -- -+ - seat = wl_container_of(seat_list->next, seat, link); - - wl_list_for_each(txs, &remote->surface_list, link) -diff --git a/transmitter/output.c b/transmitter/output.c -index 003056f..2cca781 100644 ---- a/transmitter/output.c -+++ b/transmitter/output.c -@@ -28,9 +28,12 @@ - #include - - #include "compositor.h" -+#include "compositor-drm.h" -+#include "plugin-registry.h" - - #include "plugin.h" - #include "transmitter_api.h" -+#include "waltham-renderer.h" - - /** @file - * -@@ -59,6 +62,8 @@ - * exclusive with weston_compositor_add_output(). - */ - -+static struct waltham_renderer_interface *waltham_renderer; -+ - static char * - make_model(struct weston_transmitter_remote *remote, int name) - { -@@ -146,45 +151,26 @@ transmitter_start_repaint_loop(struct weston_output *base) - } - - static int --transmitter_check_output(struct weston_transmitter_surface *txs, -- struct weston_compositor *compositor) --{ -- struct weston_output *def_output = wl_container_of(compositor->output_list.next, -- def_output, link); -- struct weston_view *view; -- -- wl_list_for_each_reverse(view, &compositor->view_list, link) { -- if (view->output == def_output) { -- if (view->surface == txs->surface) -- return 1; -- } -- } -- -- return 0; --} -- --static int - transmitter_output_repaint(struct weston_output *base, - pixman_region32_t *damage) - { - struct weston_transmitter_output* output = wl_container_of(base, output, base); - struct weston_transmitter_remote* remote = output->remote; - struct weston_transmitter* txr = remote->transmitter; -- struct weston_transmitter_api* transmitter_api = -+ struct weston_transmitter_api* transmitter_api = - weston_get_transmitter_api(txr->compositor); - struct weston_transmitter_surface* txs; - struct weston_compositor *compositor = base->compositor; - struct weston_view *view; - bool found_output = false; -+ struct timespec ts; - -- if (!output->from_frame_signal) -- return 0; -- -- output->from_frame_signal = false; -+ struct weston_drm_output_api *api = -+ weston_plugin_api_get(txr->compositor, WESTON_DRM_OUTPUT_API_NAME, sizeof(api)); - -- /* -+ /* - * Pick up weston_view in transmitter_output and check weston_view's surface -- * If the surface hasn't been conbined to weston_transmitter_surface, -+ * If the surface hasn't been conbined to weston_transmitter_surface, - * then call push_to_remote. - * If the surface has already been combined, call gather_state. - */ -@@ -201,24 +187,34 @@ transmitter_output_repaint(struct weston_output *base, - wl_list_for_each(txs, &remote->surface_list, link) { - if (txs->surface == view->surface) { - found_surface = true; -- if (!transmitter_check_output(txs, compositor)) -- break; -- - if (!txs->wthp_surf) - transmitter_api->surface_push_to_remote - (view->surface, remote, NULL); -+ -+ output->renderer->dmafd = -+ api->get_dma_fd_from_view(&output->base, view); -+ if(!output->renderer->dmafd) { -+ weston_log("Failed to get dmafd\n"); -+ goto out; -+ } -+ output->renderer->repaint_output(output); -+ output->renderer->dmafd = NULL; - transmitter_api->surface_gather_state(txs); -+ weston_buffer_reference(&view->surface->buffer_ref, NULL); - break; - } - } - if (!found_surface) -- transmitter_api->surface_push_to_remote(view->surface, -+ transmitter_api->surface_push_to_remote(view->surface, - remote, NULL); - } - } - if (!found_output) - goto out; - -+ weston_compositor_read_presentation_clock(output->base.compositor, &ts); -+ weston_output_finish_frame(&output->base, &ts, 0); -+ - return 0; - - out: -@@ -228,28 +224,38 @@ out: - } - - static void -+transmitter_assign_planes(struct weston_output *base) { -+ /* -+ * This function prevents compositor releasing buffer early. -+ */ -+ struct weston_transmitter_output* output = wl_container_of(base, output, base); -+ struct weston_transmitter_remote* remote = output->remote; -+ struct weston_transmitter_surface* txs; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_view *view; -+ -+ wl_list_for_each_reverse(view, &compositor->view_list, link) { -+ if (view->output == &output->base) { -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == view->surface) -+ view->surface->keep_buffer = true; -+ -+ } -+ } -+ } -+} -+ -+static void - transmitter_output_enable(struct weston_output *base) - { - struct weston_transmitter_output *output = wl_container_of(base, output, base); - -- output->base.assign_planes = NULL; -+ output->base.assign_planes = transmitter_assign_planes; - output->base.set_backlight = NULL; - output->base.set_dpms = NULL; - output->base.switch_mode = NULL; - } - --static void --transmitter_output_frame_handler(struct wl_listener *listener, void *data) --{ -- struct weston_transmitter_output *output; -- int ret; -- -- output = wl_container_of(listener, output, frame_listener); -- output->from_frame_signal = true; -- -- ret = transmitter_output_repaint(&output->base, NULL); --} -- - int - transmitter_remote_create_output(struct weston_transmitter_remote *remote, - const struct weston_transmitter_output_info *info) -@@ -312,13 +318,15 @@ transmitter_remote_create_output(struct weston_transmitter_remote *remote, - output->remote = remote; - wl_list_insert(&remote->output_list, &output->link); - -- weston_output_enable(&output->base); -+ /* Loading a waltham renderer library */ -+ waltham_renderer = weston_load_module("waltham-renderer.so","waltham_renderer_interface"); -+ -+ if (waltham_renderer->display_create(output) < 0) { -+ weston_log("Failed to create waltham renderer display \n"); -+ return -1; -+ } - -- output->frame_listener.notify = transmitter_output_frame_handler; -- def_output = wl_container_of(txr->compositor->output_list.next, -- def_output, link); -- wl_signal_add(&def_output->frame_signal, &output->frame_listener); -- output->from_frame_signal = false; -+ weston_output_enable(&output->base); - - return 0; - -diff --git a/transmitter/plugin.c b/transmitter/plugin.c -index 1f00f33..faf28b5 100644 ---- a/transmitter/plugin.c -+++ b/transmitter/plugin.c -@@ -121,20 +121,20 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs) - else { - /* TODO: transmit surface state to remote */ - /* The buffer must be transmitted to remote side */ -- -+ - /* waltham */ - struct weston_surface *surf = txs->surface; - struct weston_compositor *comp = surf->compositor; - int32_t stride, data_sz, width, height; - void *data; -- -+ - width = 1; - height = 1; - stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); -- -+ - data = malloc(stride * height); - data_sz = stride * height; -- -+ - /* fake sending buffer */ - txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory, - data_sz, -@@ -143,13 +143,13 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs) - surf->height, - stride, - PIXMAN_FORMAT_BPP(comp->read_format)); -- -+ - wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs); -- -+ - wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy); - wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); - wthp_surface_commit(txs->wthp_surf); -- -+ - wth_connection_flush(remote->display->connection); - txs->attach_dx = 0; - txs->attach_dy = 0; -@@ -255,7 +255,7 @@ transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs) - weston_log("no content in seat object\n"); - if(!dpy->application) - weston_log("no content in ivi-application object\n"); -- -+ - txs->wthp_ivi_surface = wthp_ivi_application_surface_create - (dpy->application, ivi_surf->id_surface, txs->wthp_surf); - weston_log("surface ID %d\n", ivi_surf->id_surface); -@@ -313,7 +313,7 @@ transmitter_surface_push_to_remote(struct weston_surface *ws, - wl_list_init(&txs->frame_callback_list); - wl_list_init(&txs->feedback_list); - -- txs->lyt = weston_plugin_api_get(txr->compositor, -+ txs->lyt = weston_plugin_api_get(txr->compositor, - IVI_LAYOUT_API_NAME, sizeof(txs->lyt)); - } - -@@ -351,15 +351,15 @@ registry_handle_global(struct wthp_registry *registry, - struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry); - - if (strcmp(interface, "wthp_compositor") == 0) { -- assert(!dpy->compositor); -+ assert(!dpy->compositor); - dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1); - /* has no events to handle */ - } else if (strcmp(interface, "wthp_blob_factory") == 0) { -- assert(!dpy->blob_factory); -+ assert(!dpy->blob_factory); - dpy->blob_factory = (struct wthp_blob_factory *)wthp_registry_bind(registry, name, interface, 1); - /* has no events to handle */ - } else if (strcmp(interface, "wthp_seat") == 0) { -- assert(!dpy->seat); -+ assert(!dpy->seat); - dpy->seat = (struct wthp_seat *)wthp_registry_bind(registry, name, interface, 1); - wthp_seat_set_listener(dpy->seat, &seat_listener, dpy); - } else if (strcmp(interface, "wthp_ivi_application") == 0) { -@@ -486,13 +486,13 @@ waltham_mainloop(int fd, uint32_t mask, void *data) - w = &dpy->conn_watch; - if (!dpy) - goto not_running; -- -+ - if (!dpy->connection) - dpy->running = false; - - if (!dpy->running) - goto not_running; -- -+ - running_display++; - /* Dispatch queued events. */ - ret = wth_connection_dispatch(dpy->connection); -@@ -505,7 +505,7 @@ waltham_mainloop(int fd, uint32_t mask, void *data) - - /* Run any application idle tasks at this point. */ - /* (nothing to run so far) */ -- -+ - /* Flush out buffered requests. If the Waltham socket is - * full, poll it for writable too, and continue flushing then. - */ -@@ -570,9 +570,6 @@ waltham_client_init(struct waltham_display *dpy) - return -1; - } - -- /* A one-off asynchronous roundtrip, just for fun. */ -- weston_log("sending wth_display.sync...\n"); -- - dpy->running = true; - - return 0; -@@ -586,7 +583,7 @@ establish_timer_handler(void *data) - - ret = waltham_client_init(remote->display); - if(ret == -2) { -- wl_event_source_timer_update(remote->establish_timer, -+ wl_event_source_timer_update(remote->establish_timer, - ESTABLISH_CONNECTION_PERIOD); - return 0; - } -@@ -631,13 +628,13 @@ retry_timer_handler(void *data) - registry_handle_global_remove(dpy->registry, 1); - init_globals(dpy); - disconnect_surface(remote); -- wl_event_source_timer_update(remote->establish_timer, -+ wl_event_source_timer_update(remote->establish_timer, - ESTABLISH_CONNECTION_PERIOD); - - return 0; - } - else -- wl_event_source_timer_update(remote->retry_timer, -+ wl_event_source_timer_update(remote->retry_timer, - RETRY_CONNECTION_PERIOD); - return 0; - } -@@ -648,7 +645,7 @@ transmitter_connect_to_remote(struct weston_transmitter *txr) - struct weston_transmitter_remote *remote; - struct wl_event_loop *loop_est, *loop_retry; - int ret; -- -+ - wl_list_for_each_reverse(remote, &txr->remote_list, link) { - /* XXX: actually start connecting */ - /* waltham */ -@@ -658,12 +655,12 @@ transmitter_connect_to_remote(struct weston_transmitter *txr) - remote->display->remote = remote; - /* set connection establish timer */ - loop_est = wl_display_get_event_loop(txr->compositor->wl_display); -- remote->establish_timer = -+ remote->establish_timer = - wl_event_loop_add_timer(loop_est, establish_timer_handler, remote); - wl_event_source_timer_update(remote->establish_timer, 1); - /* set connection retry timer */ - loop_retry = wl_display_get_event_loop(txr->compositor->wl_display); -- remote->retry_timer = -+ remote->retry_timer = - wl_event_loop_add_timer(loop_retry, retry_timer_handler, remote); - if (ret < 0) { - weston_log("Fatal: Transmitter waltham connecting failed.\n"); -diff --git a/transmitter/plugin.h b/transmitter/plugin.h -index 116c1f6..ec776fa 100644 ---- a/transmitter/plugin.h -+++ b/transmitter/plugin.h -@@ -59,7 +59,7 @@ enum wthp_seat_capability { - }; - - /* epoll structure */ --struct watch { -+struct watch { - struct waltham_display *display; - int fd; - void (*cb)(struct watch *w, uint32_t events); -@@ -198,9 +198,7 @@ struct weston_transmitter_output { - struct frame *frame; - - struct wl_callback *frame_cb; -- struct wl_listener frame_listener; -- -- bool from_frame_signal; -+ struct renderer *renderer; - }; - - struct weston_transmitter_seat { -diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h -index 4a660a0..c473256 100644 ---- a/transmitter/transmitter_api.h -+++ b/transmitter/transmitter_api.h -@@ -265,4 +265,13 @@ weston_get_transmitter_ivi_api(struct weston_compositor *compositor) - - /* Remote compositor/output are identified by model */ - -+ -+struct renderer { -+ void (*repaint_output)(struct weston_output *base); -+ struct gst_recorder *recorder; /* gst-recorder instance */ -+ int32_t dmafd; /* dmafd received from compositor-drm */ -+ int surface_width; -+ int surface_height; -+}; -+ - #endif /* WESTON_TRANSMITTER_API_H */ -diff --git a/transmitter/waltham-renderer.c b/transmitter/waltham-renderer.c -new file mode 100644 -index 0000000..f9e4e21 ---- /dev/null -+++ b/transmitter/waltham-renderer.c -@@ -0,0 +1,166 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include "compositor.h" -+#include "libweston/gst-recorder.h" -+ -+#include "transmitter_api.h" -+#include "waltham-renderer.h" -+#include "plugin.h" -+ -+struct waltham_renderer { -+ struct renderer base; -+}; -+ -+static void -+recorder_frame_notify(struct weston_transmitter_output* output) -+{ -+ gst_recorder_frame_dmafd(output->renderer->recorder, output->renderer->dmafd, -+ output->renderer->surface_width*4); -+} -+ -+static int parse_crop_rect(const char *s, struct v4l2_rect* crop) -+{ -+ crop->left = 0; -+ crop->top = 0; -+ crop->width = 0; -+ crop->height = 0; -+ -+ if (sscanf(s, "%dx%d@%dx%d", -+ &crop->width, -+ &crop->height, -+ &crop->top, -+ &crop->left) != 4) -+ return -1; -+ -+ return 0; -+} -+ -+static int -+recorder_enable(struct weston_transmitter_output *output) -+{ -+ int enable_recorder = 0; -+ struct gst_recorder_settings *settings; -+ struct weston_config_section *section; -+ -+ struct weston_output* base = &output->base; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_transmitter_remote* remote = output->remote; -+ -+ /* -+ * Limitation: -+ * Hard coding bitrate and crop params. -+ * In case of gst-recorder case these were taken from weston.ini -+ */ -+ int32_t bitrate = 3000000; -+ char *crop_params = "384x368@0x0"; -+ -+ struct v4l2_rect crop = { .width = output->base.current_mode->width, -+ .height = output->base.current_mode->height, -+ .top = 0, -+ .left = 0 }; -+ -+ if (output->renderer->recorder) -+ return -1; -+ -+ settings = malloc(sizeof(* settings)); -+ settings->ip = remote->addr; -+ -+ settings->port = atoi(remote->port); -+ -+ settings->bitrate = bitrate; -+ settings->width = output->base.current_mode->width; -+ settings->height = output->base.current_mode->height; -+ -+ settings->crop = crop; -+ -+ if (parse_crop_rect(crop_params, &settings->crop)) { -+ weston_log("[gst recorder] %s:" -+ " failed to parse crop parameter\n", -+ output->base.name); -+ goto err; -+ } -+ -+ weston_log("gst-setting are :-->\n"); -+ weston_log("ip = %s \n",settings->ip); -+ weston_log("port = %d \n",settings->port); -+ weston_log("bitrate = %d \n",settings->bitrate); -+ weston_log("crop = %d x %d \n",settings->crop.width,settings->crop.height); -+ weston_log("width = %d \n",settings->width); -+ weston_log("width = %d \n",settings->height); -+ -+ -+ gst_recorder_init(); -+ -+ output->renderer->recorder = -+ gst_recorder_create(settings); -+ if (!output->renderer->recorder) { -+ weston_log("[gst recorder] %s:" -+ " failed to create gst recorder\n", -+ output->base.name); -+ goto err; -+ } -+ -+ weston_log("[gst recorder] %s:" -+ " recorder initialized\n", -+ output->base.name); -+ -+ return 0; -+err: -+ weston_log("[gst recorder] %s:" -+ " invalid settings\n", -+ output->base.name); -+ free(settings); -+ return -1; -+} -+ -+static void waltham_renderer_repaint_output(struct weston_transmitter_output *output) -+{ -+ recorder_frame_notify(output); -+} -+ -+static int -+waltham_renderer_display_create(struct weston_transmitter_output *output) -+{ -+ struct waltham_renderer *wth_renderer; -+ -+ wth_renderer = zalloc(sizeof *wth_renderer); -+ if (wth_renderer == NULL) -+ return -1; -+ wth_renderer->base.repaint_output = waltham_renderer_repaint_output; -+ -+ output->renderer = &wth_renderer->base; -+ -+ recorder_enable(&output->base); -+ return 0; -+} -+ -+WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = { -+ .display_create = waltham_renderer_display_create -+}; -diff --git a/transmitter/waltham-renderer.h b/transmitter/waltham-renderer.h -new file mode 100644 -index 0000000..458794e ---- /dev/null -+++ b/transmitter/waltham-renderer.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#ifndef TRANSMITTER_WALTHAM_RENDERER_H_ -+#define TRANSMITTER_WALTHAM_RENDERER_H_ -+ -+struct waltham_renderer_interface { -+ int (*display_create)(struct weston_transmitter_output *output); -+}; -+ -+#endif /* TRANSMITTER_WALTHAM_RENDERER_H_ */ --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend b/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend index f23f5e2fa..fe1e1a11f 100644 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend @@ -18,19 +18,9 @@ SRC_URI_append = "\ file://0014-simple-shm-remove-ivi-application-support.patch \ file://0015-window-client-remove-ivi-application-support.patch \ file://0016-ivi-shell_add_screen_remove_layer_api.patch \ - file://0017-transmitter-add-an-incomplete-plugin-output-and-poin.patch \ - file://0018-ivi-layout-Register-ivi-layout-interface-It-enables-.patch \ - file://0019-transmitter-transmitter-plugin-for-waltham-protocol.patch \ - file://0020-compositor-add-output-type-to-weston_output.patch \ - file://0021-transmitter-add-output-type-for-waltham-output.patch \ - file://0022-transmitter-did-code-cleaning.patch \ - file://0023-compositor-drm-introduce-drm_get_dmafd_from_view.patch \ - file://0024-transmitter-introduce-waltham-renderer.patch \ + file://0017-ivi-shell-register-ivi_layout_interface.patch \ + file://0018-compositor-add-output-type-to-weston_output.patch \ + file://0019-compositor-drm-introduce-drm_get_dmafd_from_view.patch \ " -DEPENDS += "waltham" - -EXTRA_OECONF_append = " --enable-sys-uid \ - --enable-surface-remoting \ - " - +EXTRA_OECONF_append = " --enable-sys-uid"