feat(driver): import Wayland driver from v8 (#6549)

This commit is contained in:
Erik Tagirov
2024-08-23 22:03:55 +02:00
committed by GitHub
parent aebb4d3ad3
commit e186b4c8b6
15 changed files with 4069 additions and 1 deletions
+1
View File
@@ -24,6 +24,7 @@ test_screenshot_error.h
build/
tests/build_*/
tests/report/
tests/wayland_protocols/
.DS_Store
.vscode
.idea
+12
View File
@@ -1562,6 +1562,18 @@ menu "LVGL configuration"
With 2 buffers in flush_cb only and address change is required.
endchoice
config LV_USE_WAYLAND
bool "Use the wayland client to open a window and handle inputs on Linux or BSD"
default n
config LV_WAYLAND_WINDOW_DECORATIONS
bool "Draw client side window decorations, only necessary on Mutter (GNOME)"
depends on LV_USE_WAYLAND
default n
config LV_WAYLAND_WL_SHELL
bool "Support the legacy wl_shell instead of the default XDG Shell protocol"
depends on LV_USE_WAYLAND
default n
config LV_USE_LINUX_FBDEV
bool "Use Linux framebuffer device"
default n
+1
View File
@@ -11,3 +11,4 @@ Drivers
X11
windows
opengles
wayland
+180
View File
@@ -0,0 +1,180 @@
=============================
Wayland Display/Inputs driver
=============================
Overview
--------
| The **Wayland** `driver <https://github.com/lvgl/lvgl/tree/master/src/drivers/wayland>`__ offers support for simulating the LVGL display and keyboard/mouse inputs in a desktop window.
| It is an alternative to **X11** or **SDL2**
The main purpose for this driver is for testing/debugging the LVGL application, it can also be used to run applications in 'kiosk mode'
Dependencies
------------
The wayland driver requires some dependencies.
On Ubuntu
.. code:: bash
sudo apt-get install libwayland-dev libxkbcommon-dev libwayland-bin wayland-protocols
On Fedora
.. code:: bash
sudo dnf install wayland-devel libxkbcommon-devel wayland-utils wayland-protocols-devel
Configuring the wayland driver
------------------------------
1. Enable the wayland driver in ``lv_conf.h``
.. code:: c
#define LV_USE_WAYLAND 1
2. Optional configuration options:
- Enable window decorations, only required on GNOME because out of all the available wayland compositors
**only** Mutter/GNOME enforces the use of client side decorations
.. code:: c
#define LV_WAYLAND_WINDOW_DECORATIONS 1
- Enable support for the deprecated 'wl_shell', Only useful when the BSP on the target has weston ``9.x``
.. code:: c
#define LV_WAYLAND_WL_SHELL 1
Example
-------
An example simulator is available in this `repo <https://github.com/lvgl/lv_port_linux/>`__
Usage
-----
#. In ``main.c`` ``#incude "lv_drivers/wayland/wayland.h"``
#. Enable the Wayland driver in ``lv_conf.h`` with ``LV_USE_WAYLAND 1``
#. ``LV_COLOR_DEPTH`` should be set either to ``32`` or ``16`` in ``lv_conf.h``
#. Add a display using ``lv_wayland_window_create()``,
possibly with a close callback to track the status of each display:
.. code:: c
#define H_RES (800)
#define V_RES (480)
/* Create a display */
lv_disp_t * disp = lv_wayland_create_window(H_RES, V_RES, "Window Title", close_cb);
As part of the above call, the Wayland driver will register four input devices
for each display:
* a KEYPAD connected to Wayland keyboard events
* a POINTER connected to Wayland touch events
* a POINTER connected to Wayland pointer events
* an ENCODER connected to Wayland pointer axis events
Handles for input devices of each display can be obtained using
``lv_wayland_get_indev_keyboard()``, ``lv_wayland_get_indev_touchscreen()``,
``lv_wayland_get_indev_pointer()`` and ``lv_wayland_get_indev_pointeraxis()`` respectively.
Fullscreen mode
^^^^^^^^^^^^^^^
To programmatically fullscreen the window,
use the ``lv_wayland_window_set_fullscreen()`` function respectively with ``true``
or ``false`` for the ``fullscreen`` argument.
Maximized mode
^^^^^^^^^^^^^^
To programmatically maximize the window,
use the ``lv_wayland_window_set_maximized()`` function respectively with ``true``
or ``false`` for the ``maximized`` argument.
Custom timer handler
^^^^^^^^^^^^^^^^^^^^
Always call ``lv_wayland_timer_handler()`` in your timer loop instead of the regular ``lv_timer_handler()``.
**Note:** ``lv_wayland_timer_handler()`` internally calls ``lv_timer_handler()``
This allows the wayland client to work on well on weston, resizing shared memory buffers during
a commit does not work well on weston.
Wrapping the call to ``lv_timer_hander()`` is a necessity to have more control over
when the LVGL flush callback is called.
The custom timer handler returns ``false`` if the frame from previous cycle is not rendered.
When this happens, it usually means that the application is minimized or hidden behind another window.
Causing the driver to wait until the arrival of any message on the wayland socket, the process is in interruptible sleep.
Building the wayland driver
---------------------------
An example simulator is available in this `repo <https://github.com/lvgl/lv_port_linux/>`__
If there is a need to use driver with another build system. The source and header files for the XDG shell
must be generated from the definitions for the XDG shell protocol.
In the example Cmake is used to perform the operation by invoking the ``wayland-scanner`` utility
To achieve this manually,
Make sure the dependencies listed at the start of the article are installed.
The wayland protocol is defined using XML files which are present in ``/usr/share/wayland-protocols``
To generate the required files run the following commands:
.. code-block:: sh
wayland-scanner client-header </usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > wayland_xdg_shell.h
wayland-scanner private-code </usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > wayland_xdg_shell.c
The resulting files can then be integrated into the project, it's better to re-run ``wayland-scanner`` on
each build to ensure that the correct versions are generated, they must match the version of the ``wayland-client``
dynamically linked library installed on the system.
Current state and objectives
----------------------------
* Add direct rendering mode
* Refactor the shell integrations to avoid excessive conditional compilation
* Technically, the wayland driver allows to create multiple windows - but this feature is experimental.
* Eventually add enhanced support for XDG shell to allow the creation of desktop apps on Unix-like platforms,
similar to what the win32 driver does.
* Add a support for Mesa, currently wl_shm is used and it's not the most effective technique.
Bug reports
-----------
The wayland driver is currently under construction, bug reports, contributions and feedback is always welcome.
It is however important to create detailed issues when a problem is encountered, logs and screenshots of the problem are of great help.
Please enable ``LV_USE_LOG`` and launch the simulator executable like so
.. code::
WAYLAND_DEBUG=1 ./path/to/simulator_executable > /tmp/debug 2>&1
This will create a log file called ``debug`` in the ``/tmp`` directory, copy-paste the content of the file in the github issue.
The log file contains LVGL logs and the wayland messages.
Be sure to replicate the problem quickly otherwise the logs become too big
+7
View File
@@ -955,6 +955,13 @@
#define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/
#endif
/*Use Wayland to open a window and handle input on Linux or BSD desktops */
#define LV_USE_WAYLAND 0
#if LV_USE_WAYLAND
#define LV_WAYLAND_WINDOW_DECORATIONS 0 /*Draw client side window decorations only necessary on Mutter/GNOME*/
#define LV_WAYLAND_WL_SHELL 0 /*Use the legacy wl_shell protocol instead of the default XDG shell*/
#endif
/*Driver for /dev/fb*/
#define LV_USE_LINUX_FBDEV 0
#if LV_USE_LINUX_FBDEV
+3 -1
View File
@@ -11,5 +11,7 @@ sudo apt install gcc gcc-multilib g++-multilib ninja-build \
libpng-dev libjpeg-turbo8-dev libfreetype6-dev \
libglew-dev libglfw3-dev libsdl2-dev libsdl2-image-dev \
libpng-dev:i386 libjpeg-dev:i386 libfreetype6-dev:i386 \
ruby-full gcovr cmake python3 pngquant libinput-dev libxkbcommon-dev libdrm-dev pkg-config
ruby-full gcovr cmake python3 pngquant libinput-dev libxkbcommon-dev \
libdrm-dev pkg-config wayland-protocols libwayland-dev libwayland-bin \
libwayland-dev:i386 libxkbcommon-dev:i386
pip3 install pypng lz4
+2
View File
@@ -43,6 +43,8 @@ extern "C" {
#include "qnx/lv_qnx.h"
#include "wayland/lv_wayland.h"
/*********************
* DEFINES
*********************/
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
/*******************************************************************
*
* @file lv_wayland.h - Public functions of the LVGL Wayland client
*
* Based on the original file from the repository.
*
* Porting to LVGL 9.1
* 2024 EDGEMTech Ltd.
*
* See LICENCE.txt for details
*
* Author(s): EDGEMTech Ltd, Erik Tagirov (erik.tagirov@edgemtech.ch)
*
******************************************************************/
#ifndef LV_WAYLAND_H
#define LV_WAYLAND_H
#ifndef _WIN32
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../display/lv_display.h"
#include "../../indev/lv_indev.h"
#if LV_USE_WAYLAND
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef bool (*lv_wayland_display_close_f_t)(lv_display_t * disp);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Retrieves the file descriptor of the wayland socket
*/
int lv_wayland_get_fd(void);
/**
* Creates a window
* @param hor_res The width of the window in pixels
* @param ver_res The height of the window in pixels
* @param title The title of the window
* @param close_cb The callback that will be execute when the user closes the window
* @return The LVGL display associated to the window
*/
lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char * title,
lv_wayland_display_close_f_t close_cb);
/**
* Closes the window programmatically
* @param disp Reference to the LVGL display associated to the window
*/
void lv_wayland_window_close(lv_display_t * disp);
/**
* Check if the window is open
* @param disp Reference to the LVGL display associated to the window
* @return true: The window is open
*/
bool lv_wayland_window_is_open(lv_display_t * disp);
/**
* Sets the fullscreen state of the window
* @param disp Reference to the LVGL display associated to the window
* @param fullscreen If true the window enters fullscreen
*/
void lv_wayland_window_set_fullscreen(lv_display_t * disp, bool fullscreen);
/**
* Sets the maximized state of the window
* @param disp Reference to the LVGL display associated to the window
* @param fullscreen If true the window is maximized
*/
void lv_wayland_window_set_maximized(lv_display_t * disp, bool maximize);
/**
* Obtains the input device of the mouse pointer
* @note It is used to create an input group on application start
* @param disp Reference to the LVGL display associated to the window
* @return The input device
*/
lv_indev_t * lv_wayland_get_pointer(lv_display_t * disp);
/**
* Obtains the input device of the encoder
* @note It is used to create an input group on application start
* @param disp Reference to the LVGL display associated to the window
* @return The input device
*/
lv_indev_t * lv_wayland_get_pointeraxis(lv_display_t * disp);
/**
* Obtains the input device of the keyboard
* @note It is used to create an input group on application start
* @param disp Reference to the LVGL display associated to the window
* @return The input device
*/
lv_indev_t * lv_wayland_get_keyboard(lv_display_t * disp);
/**
* Obtains the input device of the touch screen
* @note It is used to create an input group on application start
* @param disp Reference to the LVGL display associated to the window
* @return The input device
*/
lv_indev_t * lv_wayland_get_touchscreen(lv_display_t * disp);
/**
* Wrapper around lv_timer_handler
* @note Must be called in the application run loop instead of the
* regular lv_timer_handler provided by LVGL
* @return true: if the cycle was completed, false if the application
* went to sleep because the last frame wasn't completed
*/
bool lv_wayland_timer_handler(void);
/**********************
* MACROS
**********************/
#endif /* LV_USE_WAYLAND */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _WIN32 */
#endif /* WAYLAND_H */
File diff suppressed because it is too large Load Diff
+105
View File
@@ -0,0 +1,105 @@
/**
* @file lv_wayland_smm.h
*
*/
#ifndef LV_WAYLAND_SMM_H
#define LV_WAYLAND_SMM_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _WIN32
/*********************
* INCLUDES
*********************/
#include "../../display/lv_display.h"
#include LV_STDDEF_INCLUDE
#include LV_STDBOOL_INCLUDE
#if LV_USE_WAYLAND
/*********************
* DEFINES
*********************/
#define SMM_FD_NAME "lvgl-wayland"
#define SMM_POOL_TAGS (1)
#define SMM_BUFFER_TAGS (2)
#define SMM_GROUP_TAGS (1)
/**********************
* TYPEDEFS
**********************/
typedef void smm_pool_t;
typedef void smm_buffer_t;
typedef void smm_group_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
struct smm_events {
void * ctx;
bool (*new_pool)(void * ctx, smm_pool_t * pool);
void (*expand_pool)(void * ctx, smm_pool_t * pool);
void (*free_pool)(void * ctx, smm_pool_t * pool);
bool (*new_buffer)(void * ctx, smm_buffer_t * buf);
bool (*init_buffer)(void * ctx, smm_buffer_t * buf);
void (*free_buffer)(void * ctx, smm_buffer_t * buf);
};
struct smm_pool_properties {
void * tag[SMM_POOL_TAGS];
size_t size;
int fd;
};
struct smm_buffer_properties {
void * tag[SMM_BUFFER_TAGS];
smm_group_t * const group;
smm_pool_t * const pool;
size_t offset;
};
struct smm_group_properties {
void * tag[SMM_GROUP_TAGS];
};
void smm_init(struct smm_events * evs);
void smm_setctx(void * ctx);
void smm_deinit(void);
smm_group_t * smm_create(void);
void smm_resize(smm_group_t * grp, size_t sz);
void smm_destroy(smm_group_t * grp);
smm_buffer_t * smm_acquire(smm_group_t * grp);
void * smm_map(smm_buffer_t * buf);
void smm_release(smm_buffer_t * buf);
smm_buffer_t * smm_latest(smm_group_t * grp);
smm_buffer_t * smm_next(smm_buffer_t * buf);
/**********************
* MACROS
**********************/
#define SMM_POOL_PROPERTIES(p) ((const struct smm_pool_properties *)(p))
#define SMM_BUFFER_PROPERTIES(b) ((const struct smm_buffer_properties *)(b))
#define SMM_GROUP_PROPERTIES(g) ((const struct smm_group_properties *)(g))
#define SMM_TAG(o, n, v) \
do { \
void **smm_tag = (void **)((char *)o + (n * sizeof(void *))); \
*smm_tag = (v); \
} while(0)
#endif /* LV_USE_WAYLAND */
#endif /* _WIN32 */
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_WAYLAND_SMM_H */
+25
View File
@@ -3140,6 +3140,31 @@
#endif
#endif
/*Use Wayland to open a window and handle input on Linux or BSD desktops */
#ifndef LV_USE_WAYLAND
#ifdef CONFIG_LV_USE_WAYLAND
#define LV_USE_WAYLAND CONFIG_LV_USE_WAYLAND
#else
#define LV_USE_WAYLAND 0
#endif
#endif
#if LV_USE_WAYLAND
#ifndef LV_WAYLAND_WINDOW_DECORATIONS
#ifdef CONFIG_LV_WAYLAND_WINDOW_DECORATIONS
#define LV_WAYLAND_WINDOW_DECORATIONS CONFIG_LV_WAYLAND_WINDOW_DECORATIONS
#else
#define LV_WAYLAND_WINDOW_DECORATIONS 0 /*Draw client side window decorations only necessary on Mutter/GNOME*/
#endif
#endif
#ifndef LV_WAYLAND_WL_SHELL
#ifdef CONFIG_LV_WAYLAND_WL_SHELL
#define LV_WAYLAND_WL_SHELL CONFIG_LV_WAYLAND_WL_SHELL
#else
#define LV_WAYLAND_WL_SHELL 0 /*Use the legacy wl_shell protocol instead of the default XDG shell*/
#endif
#endif
#endif
/*Driver for /dev/fb*/
#ifndef LV_USE_LINUX_FBDEV
#ifdef CONFIG_LV_USE_LINUX_FBDEV
+13
View File
@@ -326,6 +326,19 @@ if(NOT WIN32)
# libjpeg is required for the jpeg test case
find_package(JPEG REQUIRED)
include_directories(${JPEG_INCLUDE_DIR})
# Wayland
find_package(PkgConfig)
pkg_check_modules(wayland-client REQUIRED wayland-client)
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
link_libraries(wayland-client wayland-cursor xkbcommon)
# Add auto generated source required for XDG shell
include_directories("${LVGL_TEST_DIR}/wayland_protocols")
target_sources(test_common PUBLIC "wayland_protocols/wayland_xdg_shell.c")
endif()
# libpng is required for the png test case
+38
View File
@@ -14,6 +14,9 @@ lvgl_test_dir = os.path.dirname(os.path.realpath(__file__))
lvgl_script_path = os.path.join(lvgl_test_dir, "../scripts")
sys.path.append(lvgl_script_path)
wayland_dir = os.path.join(lvgl_test_dir, "wayland_protocols")
wayland_protocols_dir = os.path.realpath("/usr/share/wayland-protocols")
from LVGLImage import LVGLImage, ColorFormat, CompressMethod
# Key values must match variable names in CMakeLists.txt.
@@ -70,6 +73,37 @@ def get_build_dir(options_name):
global lvgl_test_dir
return os.path.join(lvgl_test_dir, get_base_build_dir(options_name))
def gen_wayland_protocols(clean):
'''Generates the xdg shell interface from wayland protocol definitions'''
if clean:
delete_dir_ignore_missing(wayland_dir)
if not os.path.isdir(wayland_dir):
os.mkdir(wayland_dir)
subprocess.check_call(['wayland-scanner',
'client-header',
os.path.join(wayland_protocols_dir, "stable/xdg-shell/xdg-shell.xml"),
os.path.join(wayland_dir, "wayland_xdg_shell.h.original"),
])
subprocess.check_call(['wayland-scanner',
'private-code',
os.path.join(wayland_protocols_dir, "stable/xdg-shell/xdg-shell.xml"),
os.path.join(wayland_dir, "wayland_xdg_shell.c.original"),
])
# Insert guards
with open(os.path.join(wayland_dir, "wayland_xdg_shell.h"), "w") as outfile:
subprocess.check_call(['sed','-e', "1i #if LV_BUILD_TEST", '-e', '$a #endif',
os.path.join(wayland_dir, "wayland_xdg_shell.h.original")], stdout=outfile)
with open(os.path.join(wayland_dir, "wayland_xdg_shell.c"), "w") as outfile:
subprocess.check_call(['sed','-e', "1i #if LV_BUILD_TEST", '-e', '$a #endif',
os.path.join(wayland_dir, "wayland_xdg_shell.c.original")], stdout=outfile)
subprocess.check_call(['rm', os.path.join(wayland_dir, "wayland_xdg_shell.c.original")])
subprocess.check_call(['rm', os.path.join(wayland_dir, "wayland_xdg_shell.h.original")])
def build_tests(options_name, build_type, clean):
'''Build all tests for the specified options name.'''
@@ -89,6 +123,10 @@ def build_tests(options_name, build_type, clean):
delete_dir_ignore_missing(build_dir)
os.chdir(lvgl_test_dir)
if platform.system() != 'Windows':
gen_wayland_protocols(clean)
created_build_dir = False
if not os.path.isdir(build_dir):
os.mkdir(build_dir)
+5
View File
@@ -126,6 +126,11 @@
#define LV_USE_LINUX_FBDEV 1
#endif
#ifndef LV_USE_WAYLAND
#define LV_USE_WAYLAND 1
#define LV_WAYLAND_WINDOW_DECORATIONS 1
#endif
#define LV_USE_ILI9341 1
#define LV_USE_ST7735 1
#define LV_USE_ST7789 1