mirror of
https://github.com/lvgl/lvgl.git
synced 2026-06-02 09:37:42 +08:00
feat(wayland): add egl support (#9398)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
@@ -64,6 +64,46 @@ It uses Wayland's shared memory protocol (``wl_shm``) for rendering, which is su
|
|||||||
The SHM backend is enabled by default and requires no additional configuration.
|
The SHM backend is enabled by default and requires no additional configuration.
|
||||||
|
|
||||||
|
|
||||||
|
EGL Backend
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The **EGL Backend** provides hardware-accelerated rendering for the Wayland driver using OpenGL ES.
|
||||||
|
It utilizes the EGL (Embedded-System Graphics Library) interface to create OpenGL ES rendering contexts,
|
||||||
|
enabling GPU-accelerated graphics on Wayland compositors that support the necessary protocols.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
* Hardware-accelerated rendering via OpenGL ES
|
||||||
|
* Full rotation support
|
||||||
|
* Compatible with LVGL 3D rendering capabilities (see :ref:`3d_gltf_support`)
|
||||||
|
* Efficient GPU-based compositing
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
* OpenGL ES 2.0 support on the target hardware
|
||||||
|
* ``LV_USE_OPENGLES`` must be enabled in your LVGL configuration
|
||||||
|
* Must link with the ``wayland-egl`` library
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
To enable the EGL backend:
|
||||||
|
|
||||||
|
1. Enable OpenGL ES support in your LVGL configuration:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#define LV_USE_OPENGLES 1
|
||||||
|
|
||||||
|
2. Link your application with the ``wayland-egl`` library (add to your build system):
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-lwayland-egl
|
||||||
|
|
||||||
|
**Note:** If your target board has OpenGL ES 2.0 support, this backend can be used with LVGL's 3D rendering
|
||||||
|
capabilities for glTF model visualization. See :ref:`3d_gltf_support` for details on 3D rendering support.
|
||||||
|
|
||||||
|
|
||||||
G2D Backend
|
G2D Backend
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@@ -82,13 +122,20 @@ The G2D backend leverages NXP's hardware-accelerated 2D graphics engine availabl
|
|||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
Enable the G2D backend in ``lv_conf.h``:
|
To enable the G2D backend:
|
||||||
|
|
||||||
.. code:: c
|
1. Enable G2D support in your LVGL configuration:
|
||||||
|
|
||||||
#define LV_USE_DRAW_G2D 1
|
.. code-block:: c
|
||||||
|
|
||||||
When ``LV_USE_DRAW_G2D`` is enabled, the Wayland driver will automatically use the G2D backend instead of the default SHM backend.
|
#define LV_USE_G2D 1
|
||||||
|
#define LV_USE_DRAW_G2D 1
|
||||||
|
|
||||||
|
2. Link your application with the ``g2d`` library (add to your build system):
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-lg2d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -248,7 +295,6 @@ For applications that don't need decorations (fullscreen, kiosk mode, etc.), sim
|
|||||||
Current state and objectives
|
Current state and objectives
|
||||||
****************************
|
****************************
|
||||||
|
|
||||||
* EGL Support
|
|
||||||
* Server-side window decorations
|
* Server-side window decorations
|
||||||
* Rotation support for the SHM backend
|
* Rotation support for the SHM backend
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ for integration into custom graphics pipelines.
|
|||||||
|
|
||||||
For complete implementation details, see :ref:`OpenGL driver <opengl_driver>`.
|
For complete implementation details, see :ref:`OpenGL driver <opengl_driver>`.
|
||||||
|
|
||||||
|
.. _3d_gltf_support:
|
||||||
|
|
||||||
3D/glTF Support
|
3D/glTF Support
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|||||||
@@ -225,16 +225,23 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
|||||||
|
|
||||||
#if LV_USE_WAYLAND
|
#if LV_USE_WAYLAND
|
||||||
/*Automatically detect wayland backend*/
|
/*Automatically detect wayland backend*/
|
||||||
#if LV_USE_G2D
|
#if LV_USE_OPENGLES
|
||||||
|
#define LV_WAYLAND_USE_EGL 1
|
||||||
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
|
#elif LV_USE_G2D
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#define LV_WAYLAND_USE_G2D 1
|
#define LV_WAYLAND_USE_G2D 1
|
||||||
#define LV_WAYLAND_USE_SHM 0
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
#else
|
#else
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#define LV_WAYLAND_USE_G2D 0
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
#define LV_WAYLAND_USE_SHM 1
|
#define LV_WAYLAND_USE_SHM 1
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define LV_WAYLAND_USE_G2D 0
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
#define LV_WAYLAND_USE_SHM 0
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_LINUX_DRM == 0
|
#if LV_USE_LINUX_DRM == 0
|
||||||
@@ -284,7 +291,11 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LV_USE_EGL
|
#ifndef LV_USE_EGL
|
||||||
#define LV_USE_EGL LV_LINUX_DRM_USE_EGL
|
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL
|
||||||
|
#define LV_USE_EGL 1
|
||||||
|
#else
|
||||||
|
#define LV_USE_EGL 0
|
||||||
|
#endif
|
||||||
#endif /* LV_USE_EGL */
|
#endif /* LV_USE_EGL */
|
||||||
|
|
||||||
#if LV_USE_OS
|
#if LV_USE_OS
|
||||||
|
|||||||
@@ -123,7 +123,10 @@ lv_result_t lv_opengles_texture_reshape(lv_opengles_texture_t * texture, lv_disp
|
|||||||
static void lv_opengles_texture_attach_to_display(lv_opengles_texture_t * texture, lv_display_t * display)
|
static void lv_opengles_texture_attach_to_display(lv_opengles_texture_t * texture, lv_display_t * display)
|
||||||
{
|
{
|
||||||
LV_ASSERT_NULL(display);
|
LV_ASSERT_NULL(display);
|
||||||
|
LV_UNUSED(texture);
|
||||||
|
#if !LV_USE_DRAW_NANOVG
|
||||||
display->layer_head->user_data = (void *)(lv_uintptr_t)texture->texture_id;
|
display->layer_head->user_data = (void *)(lv_uintptr_t)texture->texture_id;
|
||||||
|
#endif /*!LV_USE_DRAW_NANOVG*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display)
|
static lv_result_t lv_opengles_texture_create_draw_buffers(lv_opengles_texture_t * texture, lv_display_t * display)
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct _lv_wl_window_t {
|
typedef struct _lv_wl_window_t {
|
||||||
lv_display_t * lv_disp;
|
|
||||||
void * backend_display_data;
|
void * backend_display_data;
|
||||||
|
lv_display_t * lv_disp;
|
||||||
lv_indev_t * lv_indev_pointer;
|
lv_indev_t * lv_indev_pointer;
|
||||||
lv_indev_t * lv_indev_pointeraxis;
|
lv_indev_t * lv_indev_pointeraxis;
|
||||||
lv_indev_t * lv_indev_touch;
|
lv_indev_t * lv_indev_touch;
|
||||||
|
|||||||
@@ -173,6 +173,17 @@ extern const lv_wayland_backend_ops_t wl_backend_ops;
|
|||||||
*/
|
*/
|
||||||
void * lv_wayland_get_backend_display_data(lv_display_t * display);
|
void * lv_wayland_get_backend_display_data(lv_display_t * display);
|
||||||
|
|
||||||
|
/** @brief Set the backend-specific display data
|
||||||
|
*
|
||||||
|
* The backend display data is set automatically to the return type of the
|
||||||
|
* init_display/resize_display, this function should only be used in special
|
||||||
|
* cases where it needs to be overridden temporarily
|
||||||
|
*
|
||||||
|
* @param[in] display Pointer to the LVGL display object
|
||||||
|
* @param[in] data Pointer to backend-specific display data
|
||||||
|
*/
|
||||||
|
void lv_wayland_set_backend_display_data(lv_display_t * display, void * data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Wayland surface for rendering
|
* @brief Get the Wayland surface for rendering
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,419 @@
|
|||||||
|
/** @file lv_wl_egl_backend.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_wayland_private.h"
|
||||||
|
|
||||||
|
#if LV_WAYLAND_USE_EGL
|
||||||
|
|
||||||
|
#include "../../display/lv_display_private.h"
|
||||||
|
#include "../opengles/lv_opengles_driver.h"
|
||||||
|
#include "../opengles/lv_opengles_texture_private.h"
|
||||||
|
#include "../opengles/lv_opengles_egl_private.h"
|
||||||
|
#include "../opengles/lv_opengles_debug.h"
|
||||||
|
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lv_opengles_texture_t texture;
|
||||||
|
struct wl_egl_window * egl_window;
|
||||||
|
lv_opengles_egl_t * egl_ctx;
|
||||||
|
} lv_wl_egl_display_data_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void * wl_egl_init(void);
|
||||||
|
static void wl_egl_deinit(void * backend_ctx);
|
||||||
|
static void * wl_egl_init_display(void * backend_ctx, lv_display_t * display, int32_t width, int32_t height);
|
||||||
|
static void * wl_egl_resize_display(void * backend_ctx, lv_display_t * display);
|
||||||
|
static void wl_egl_deinit_display(void * backend_ctx, lv_display_t * display);
|
||||||
|
static void wl_egl_global_handler(void * backend_ctx, struct wl_registry * registry, uint32_t name,
|
||||||
|
const char * interface, uint32_t version);
|
||||||
|
|
||||||
|
static void egl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||||
|
static void flush_wait_cb(lv_display_t * disp);
|
||||||
|
static void frame_done(void * data, struct wl_callback * callback, uint32_t time);
|
||||||
|
|
||||||
|
static lv_wl_egl_display_data_t * egl_create_display_data(lv_display_t * display,
|
||||||
|
int32_t width, int32_t height);
|
||||||
|
static void egl_destroy_display_data(lv_wl_egl_display_data_t * ddata);
|
||||||
|
|
||||||
|
static lv_egl_interface_t wl_egl_get_interface(lv_display_t * display);
|
||||||
|
static void * wl_egl_create_window(void * driver_data, const lv_egl_native_window_properties_t * properties);
|
||||||
|
static void wl_egl_destroy_window(void * driver_data, void * native_window);
|
||||||
|
static size_t wl_egl_select_config_cb(void * driver_data, const lv_egl_config_t * configs, size_t config_count);
|
||||||
|
static void wl_egl_flip_cb(void * driver_data, bool vsync);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
|
||||||
|
static const struct wl_callback_listener frame_listener = {
|
||||||
|
.done = frame_done,
|
||||||
|
};
|
||||||
|
|
||||||
|
const lv_wayland_backend_ops_t wl_backend_ops = {
|
||||||
|
.init = wl_egl_init,
|
||||||
|
.deinit = wl_egl_deinit,
|
||||||
|
.global_handler = wl_egl_global_handler,
|
||||||
|
.init_display = wl_egl_init_display,
|
||||||
|
.deinit_display = wl_egl_deinit_display,
|
||||||
|
.resize_display = wl_egl_resize_display,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void frame_done(void * data, struct wl_callback * callback, uint32_t time)
|
||||||
|
{
|
||||||
|
LV_UNUSED(time);
|
||||||
|
lv_display_t * display = data;
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
lv_display_flush_ready(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * wl_egl_init(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_egl_deinit(void * backend_ctx)
|
||||||
|
{
|
||||||
|
LV_UNUSED(backend_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_wl_egl_display_data_t * egl_create_display_data(lv_display_t * display,
|
||||||
|
int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_zalloc(sizeof(*ddata));
|
||||||
|
if(!ddata) {
|
||||||
|
LV_LOG_ERROR("Failed to allocate data for display");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the backend display data immediately as we will need it
|
||||||
|
* in the EGL window creation callback */
|
||||||
|
lv_wayland_set_backend_display_data(display, ddata);
|
||||||
|
|
||||||
|
|
||||||
|
/* Create EGL context */
|
||||||
|
lv_egl_interface_t egl_interface = wl_egl_get_interface(display);
|
||||||
|
ddata->egl_ctx = lv_opengles_egl_context_create(&egl_interface);
|
||||||
|
if(!ddata->egl_ctx) {
|
||||||
|
LV_LOG_ERROR("Failed to create EGL context");
|
||||||
|
goto egl_ctx_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the opengles texture driver handle the texture lifetime */
|
||||||
|
ddata->texture.is_texture_owner = true;
|
||||||
|
|
||||||
|
/*Initialize the draw buffers and texture*/
|
||||||
|
lv_result_t res = lv_opengles_texture_reshape(&ddata->texture, display, width, height);
|
||||||
|
if(res != LV_RESULT_OK) {
|
||||||
|
LV_LOG_ERROR("Failed to create draw buffers");
|
||||||
|
goto texture_err;
|
||||||
|
}
|
||||||
|
return ddata;
|
||||||
|
|
||||||
|
texture_err:
|
||||||
|
lv_opengles_egl_context_destroy(ddata->egl_ctx);
|
||||||
|
egl_ctx_err:
|
||||||
|
lv_wayland_set_backend_display_data(display, NULL);
|
||||||
|
lv_free(ddata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_destroy_display_data(lv_wl_egl_display_data_t * ddata)
|
||||||
|
{
|
||||||
|
if(!ddata) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_opengles_texture_deinit(&ddata->texture);
|
||||||
|
|
||||||
|
if(ddata->egl_ctx) {
|
||||||
|
lv_opengles_egl_context_destroy(ddata->egl_ctx);
|
||||||
|
ddata->egl_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LV_LOG_INFO("Deleted EGL display data");
|
||||||
|
lv_free(ddata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_wait_cb(lv_display_t * disp)
|
||||||
|
{
|
||||||
|
while(disp->flushing) {
|
||||||
|
wl_display_dispatch(lv_wl_ctx.wl_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_OPENGLES || LV_USE_DRAW_NANOVG
|
||||||
|
|
||||||
|
static void egl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||||
|
{
|
||||||
|
LV_UNUSED(area);
|
||||||
|
LV_UNUSED(px_map);
|
||||||
|
|
||||||
|
int32_t disp_width = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t disp_height = lv_display_get_vertical_resolution(disp);
|
||||||
|
if(!lv_display_flush_is_last(disp)) {
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(disp);
|
||||||
|
struct wl_surface * surface = lv_wayland_get_window_surface(disp);
|
||||||
|
|
||||||
|
if(!surface) {
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_OPENGLES
|
||||||
|
lv_opengles_viewport(0, 0, lv_display_get_original_horizontal_resolution(disp),
|
||||||
|
lv_display_get_original_vertical_resolution(disp));
|
||||||
|
lv_opengles_render_display_texture(disp, false, true);
|
||||||
|
#endif /*LV_USE_DRAW_OPENGLES*/
|
||||||
|
|
||||||
|
/* Swap buffers through EGL */
|
||||||
|
lv_opengles_egl_update(ddata->egl_ctx);
|
||||||
|
|
||||||
|
/* Request frame callback for vsync */
|
||||||
|
struct wl_callback * callback = wl_surface_frame(surface);
|
||||||
|
wl_callback_add_listener(callback, &frame_listener, disp);
|
||||||
|
wl_surface_damage(surface, 0, 0, disp_width, disp_height);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static void egl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
|
||||||
|
{
|
||||||
|
LV_UNUSED(px_map);
|
||||||
|
LV_UNUSED(area);
|
||||||
|
|
||||||
|
if(!lv_display_flush_is_last(disp)) {
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(disp);
|
||||||
|
struct wl_surface * surface = lv_wayland_get_window_surface(disp);
|
||||||
|
|
||||||
|
if(!surface) {
|
||||||
|
lv_display_flush_ready(disp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t disp_width = lv_display_get_horizontal_resolution(disp);
|
||||||
|
int32_t disp_height = lv_display_get_vertical_resolution(disp);
|
||||||
|
|
||||||
|
lv_opengles_viewport(0, 0, lv_display_get_original_horizontal_resolution(disp),
|
||||||
|
lv_display_get_original_vertical_resolution(disp));
|
||||||
|
|
||||||
|
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(disp_width, cf);
|
||||||
|
|
||||||
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, ddata->texture.texture_id));
|
||||||
|
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||||
|
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / lv_color_format_get_size(cf)));
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 16
|
||||||
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, disp_width, disp_height, 0, GL_RGB,
|
||||||
|
GL_UNSIGNED_SHORT_5_6_5, ddata->texture.fb1));
|
||||||
|
#elif LV_COLOR_DEPTH == 32
|
||||||
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, disp_width, disp_height, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, ddata->texture.fb1));
|
||||||
|
#else
|
||||||
|
#error("Unsupported color format")
|
||||||
|
#endif
|
||||||
|
lv_opengles_render_params_t params = {
|
||||||
|
.h_flip = false,
|
||||||
|
.v_flip = false,
|
||||||
|
.rb_swap = LV_COLOR_DEPTH == 32,
|
||||||
|
};
|
||||||
|
lv_opengles_render_display(disp, ¶ms);
|
||||||
|
lv_opengles_egl_update(ddata->egl_ctx);
|
||||||
|
|
||||||
|
struct wl_callback * callback = wl_surface_frame(surface);
|
||||||
|
wl_callback_add_listener(callback, &frame_listener, disp);
|
||||||
|
|
||||||
|
wl_surface_damage(surface, 0, 0, disp_width, disp_height);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void * wl_egl_init_display(void * backend_ctx, lv_display_t * display, int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
LV_UNUSED(backend_ctx);
|
||||||
|
lv_wl_egl_display_data_t * ddata = egl_create_display_data(display, width, height);
|
||||||
|
if(!ddata) {
|
||||||
|
LV_LOG_ERROR("Failed to create display data");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_display_set_flush_cb(display, egl_flush_cb);
|
||||||
|
lv_display_set_flush_wait_cb(display, flush_wait_cb);
|
||||||
|
lv_display_set_render_mode(display, LV_USE_DRAW_NANOVG ? LV_DISPLAY_RENDER_MODE_FULL : LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||||
|
|
||||||
|
return ddata;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * wl_egl_resize_display(void * backend_ctx, lv_display_t * display)
|
||||||
|
{
|
||||||
|
LV_UNUSED(backend_ctx);
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(display);
|
||||||
|
|
||||||
|
int32_t width = lv_display_get_horizontal_resolution(display);
|
||||||
|
int32_t height = lv_display_get_vertical_resolution(display);
|
||||||
|
lv_result_t res = lv_opengles_texture_reshape(&ddata->texture, display, width, height);
|
||||||
|
if(res != LV_RESULT_OK) {
|
||||||
|
LV_LOG_ERROR("Failed to resize display");
|
||||||
|
return ddata;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_egl_window_resize(ddata->egl_window, width, height, 0, 0);
|
||||||
|
return ddata;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_egl_deinit_display(void * backend_ctx, lv_display_t * display)
|
||||||
|
{
|
||||||
|
LV_UNUSED(backend_ctx);
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(display);
|
||||||
|
egl_destroy_display_data(ddata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_egl_global_handler(void * backend_ctx, struct wl_registry * registry, uint32_t name,
|
||||||
|
const char * interface, uint32_t version)
|
||||||
|
{
|
||||||
|
LV_UNUSED(backend_ctx);
|
||||||
|
LV_UNUSED(registry);
|
||||||
|
LV_UNUSED(name);
|
||||||
|
LV_UNUSED(interface);
|
||||||
|
LV_UNUSED(version);
|
||||||
|
|
||||||
|
/* No specific Wayland globals needed for basic EGL support */
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_egl_interface_t wl_egl_get_interface(lv_display_t * display)
|
||||||
|
{
|
||||||
|
return (lv_egl_interface_t) {
|
||||||
|
.driver_data = display,
|
||||||
|
.native_display = lv_wl_ctx.wl_display,
|
||||||
|
.egl_platform = EGL_PLATFORM_WAYLAND_KHR,
|
||||||
|
.select_config = wl_egl_select_config_cb,
|
||||||
|
.flip_cb = wl_egl_flip_cb,
|
||||||
|
.create_window_cb = wl_egl_create_window,
|
||||||
|
.destroy_window_cb = wl_egl_destroy_window,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t wl_egl_select_config_cb(void * driver_data, const lv_egl_config_t * configs, size_t config_count)
|
||||||
|
{
|
||||||
|
lv_display_t * display = (lv_display_t *)driver_data;
|
||||||
|
int32_t target_w = lv_display_get_horizontal_resolution(display);
|
||||||
|
int32_t target_h = lv_display_get_vertical_resolution(display);
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 16
|
||||||
|
lv_color_format_t target_cf = LV_COLOR_FORMAT_RGB565;
|
||||||
|
#elif LV_COLOR_DEPTH == 32
|
||||||
|
lv_color_format_t target_cf = LV_COLOR_FORMAT_ARGB8888;
|
||||||
|
#else
|
||||||
|
#error("Unsupported color format")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(size_t i = 0; i < config_count; ++i) {
|
||||||
|
LV_LOG_TRACE("Got config %zu %#x %dx%d %d %d %d %d buffer size %d depth %d samples %d stencil %d surface type %d",
|
||||||
|
i, configs[i].id,
|
||||||
|
configs[i].max_width, configs[i].max_height,
|
||||||
|
configs[i].r_bits, configs[i].g_bits, configs[i].b_bits, configs[i].a_bits,
|
||||||
|
configs[i].buffer_size, configs[i].depth, configs[i].samples,
|
||||||
|
configs[i].stencil, configs[i].surface_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < config_count; ++i) {
|
||||||
|
lv_color_format_t config_cf = lv_opengles_egl_color_format_from_egl_config(&configs[i]);
|
||||||
|
if(configs[i].max_width >= target_w &&
|
||||||
|
configs[i].max_height >= target_h &&
|
||||||
|
config_cf == target_cf &&
|
||||||
|
configs[i].surface_type & EGL_WINDOW_BIT) {
|
||||||
|
LV_LOG_TRACE("Choosing config %zu", i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * wl_egl_create_window(void * driver_data, const lv_egl_native_window_properties_t * properties)
|
||||||
|
{
|
||||||
|
LV_UNUSED(properties);
|
||||||
|
lv_display_t * display = (lv_display_t *)driver_data;
|
||||||
|
|
||||||
|
struct wl_surface * wl_surface = lv_wayland_get_window_surface(display);
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(display);
|
||||||
|
|
||||||
|
if(!wl_surface) {
|
||||||
|
LV_LOG_ERROR("Failed to get Wayland surface");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddata->egl_window = wl_egl_window_create(wl_surface,
|
||||||
|
lv_display_get_horizontal_resolution(display),
|
||||||
|
lv_display_get_vertical_resolution(display));
|
||||||
|
if(!ddata->egl_window) {
|
||||||
|
LV_LOG_ERROR("Failed to create wl_egl_window");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ddata->egl_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_egl_destroy_window(void * driver_data, void * native_window)
|
||||||
|
{
|
||||||
|
lv_display_t * display = (lv_display_t *)driver_data;
|
||||||
|
lv_wl_egl_display_data_t * ddata = lv_wayland_get_backend_display_data(display);
|
||||||
|
|
||||||
|
LV_ASSERT(ddata->egl_window == native_window);
|
||||||
|
if(ddata->egl_window) {
|
||||||
|
wl_egl_window_destroy(ddata->egl_window);
|
||||||
|
ddata->egl_window = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_egl_flip_cb(void * driver_data, bool vsync)
|
||||||
|
{
|
||||||
|
LV_UNUSED(driver_data);
|
||||||
|
LV_UNUSED(vsync);
|
||||||
|
|
||||||
|
/* For Wayland, buffer swapping is handled by the compositor
|
||||||
|
* through wl_surface_commit() which is called in the flush callback */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_WAYLAND_USE_EGL*/
|
||||||
@@ -87,11 +87,11 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char
|
|||||||
goto create_window_err;
|
goto create_window_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_display_set_driver_data(window->lv_disp, window);
|
||||||
|
|
||||||
/* Initialize display driver */
|
/* Initialize display driver */
|
||||||
window->backend_display_data = wl_backend_ops.init_display(lv_wl_ctx.backend_data, window->lv_disp, hor_res, ver_res);
|
window->backend_display_data = wl_backend_ops.init_display(lv_wl_ctx.backend_data, window->lv_disp, hor_res, ver_res);
|
||||||
|
|
||||||
lv_display_set_driver_data(window->lv_disp, window);
|
|
||||||
|
|
||||||
lv_wayland_xdg_configure_surface(window);
|
lv_wayland_xdg_configure_surface(window);
|
||||||
|
|
||||||
lv_display_add_event_cb(window->lv_disp, res_changed_event, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
lv_display_add_event_cb(window->lv_disp, res_changed_event, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||||
@@ -148,6 +148,14 @@ void * lv_wayland_get_backend_display_data(lv_display_t * display)
|
|||||||
return window->backend_display_data;
|
return window->backend_display_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lv_wayland_set_backend_display_data(lv_display_t * display, void * data)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(display);
|
||||||
|
lv_wl_window_t * window = lv_display_get_driver_data(display);
|
||||||
|
LV_ASSERT_NULL(window);
|
||||||
|
window->backend_display_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
struct wl_surface * lv_wayland_get_window_surface(lv_display_t * display)
|
struct wl_surface * lv_wayland_get_window_surface(lv_display_t * display)
|
||||||
{
|
{
|
||||||
LV_ASSERT_NULL(display);
|
LV_ASSERT_NULL(display);
|
||||||
|
|||||||
+13
-2
@@ -4835,16 +4835,23 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
|||||||
|
|
||||||
#if LV_USE_WAYLAND
|
#if LV_USE_WAYLAND
|
||||||
/*Automatically detect wayland backend*/
|
/*Automatically detect wayland backend*/
|
||||||
#if LV_USE_G2D
|
#if LV_USE_OPENGLES
|
||||||
|
#define LV_WAYLAND_USE_EGL 1
|
||||||
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
|
#elif LV_USE_G2D
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#define LV_WAYLAND_USE_G2D 1
|
#define LV_WAYLAND_USE_G2D 1
|
||||||
#define LV_WAYLAND_USE_SHM 0
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
#else
|
#else
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#define LV_WAYLAND_USE_G2D 0
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
#define LV_WAYLAND_USE_SHM 1
|
#define LV_WAYLAND_USE_SHM 1
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define LV_WAYLAND_USE_G2D 0
|
#define LV_WAYLAND_USE_G2D 0
|
||||||
#define LV_WAYLAND_USE_SHM 0
|
#define LV_WAYLAND_USE_SHM 0
|
||||||
|
#define LV_WAYLAND_USE_EGL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_LINUX_DRM == 0
|
#if LV_USE_LINUX_DRM == 0
|
||||||
@@ -4894,7 +4901,11 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LV_USE_EGL
|
#ifndef LV_USE_EGL
|
||||||
#define LV_USE_EGL LV_LINUX_DRM_USE_EGL
|
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL
|
||||||
|
#define LV_USE_EGL 1
|
||||||
|
#else
|
||||||
|
#define LV_USE_EGL 0
|
||||||
|
#endif
|
||||||
#endif /* LV_USE_EGL */
|
#endif /* LV_USE_EGL */
|
||||||
|
|
||||||
#if LV_USE_OS
|
#if LV_USE_OS
|
||||||
|
|||||||
@@ -368,10 +368,8 @@ if(NOT WIN32)
|
|||||||
pkg_check_modules(wayland_client wayland-client)
|
pkg_check_modules(wayland_client wayland-client)
|
||||||
|
|
||||||
if (wayland_client_FOUND)
|
if (wayland_client_FOUND)
|
||||||
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
pkg_check_modules(WAYLAND REQUIRED wayland-cursor wayland-client wayland-egl xkbcommon)
|
||||||
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
link_libraries(${WAYLAND_LIBRARIES})
|
||||||
|
|
||||||
link_libraries(wayland-client wayland-cursor xkbcommon)
|
|
||||||
|
|
||||||
# Add auto generated source required for XDG shell
|
# Add auto generated source required for XDG shell
|
||||||
include_directories("${LVGL_TEST_DIR}/wayland_protocols")
|
include_directories("${LVGL_TEST_DIR}/wayland_protocols")
|
||||||
|
|||||||
Reference in New Issue
Block a user