mirror of
https://github.com/lvgl/lvgl.git
synced 2026-09-23 11:45:59 +08:00
feat(wayland): support falling back to different backends at runtime
This commit is contained in:
@@ -230,27 +230,6 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#define LV_LOG_TRACE_ANIM 0
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
#if LV_USE_WAYLAND
|
||||
/*Automatically detect wayland backend*/
|
||||
#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_SHM 0
|
||||
#else
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#define LV_WAYLAND_USE_G2D 0
|
||||
#define LV_WAYLAND_USE_SHM 1
|
||||
#endif
|
||||
#else
|
||||
#define LV_WAYLAND_USE_G2D 0
|
||||
#define LV_WAYLAND_USE_SHM 0
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#if LV_USE_LINUX_DRM
|
||||
#if LV_USE_OPENGLES
|
||||
#define LV_LINUX_DRM_USE_EGL 1
|
||||
@@ -309,6 +288,12 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#define LV_SDL_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#if LV_USE_WAYLAND && LV_USE_OPENGLES
|
||||
#define LV_WAYLAND_USE_EGL 1
|
||||
#else
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#ifndef LV_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL || LV_SDL_USE_EGL
|
||||
#define LV_USE_EGL 1
|
||||
|
||||
@@ -125,8 +125,7 @@ lv_result_t lv_wayland_init(void)
|
||||
LV_LOG_ERROR("failed to connect to Wayland server");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_wl_ctx.backend_data = wl_backend_ops.init();
|
||||
lv_wayland_backend_init_all();
|
||||
|
||||
/* Add registry listener and wait for registry reception */
|
||||
lv_wl_ctx.wl_registry = wl_display_get_registry(lv_wl_ctx.wl_display);
|
||||
@@ -167,7 +166,7 @@ void lv_wayland_deinit(void)
|
||||
lv_wayland_xdg_deinit();
|
||||
|
||||
if(is_wayland_initialized) {
|
||||
wl_backend_ops.deinit(lv_wl_ctx.backend_data);
|
||||
lv_wayland_backend_deinit_all();
|
||||
}
|
||||
|
||||
if(lv_wl_ctx.seat.wl_seat) {
|
||||
@@ -324,8 +323,7 @@ static void handle_global(void * data, struct wl_registry * registry, uint32_t n
|
||||
ctx->wl_output_count++;
|
||||
}
|
||||
}
|
||||
|
||||
wl_backend_ops.global_handler(lv_wl_ctx.backend_data, registry, name, interface, version);
|
||||
lv_wayland_backend_global_handler(registry, name, interface, version);
|
||||
}
|
||||
|
||||
static void handle_global_remove(void * data, struct wl_registry * registry, uint32_t name)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file lv_wayland_backend.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_wayland_backend_private.h"
|
||||
|
||||
#if LV_USE_WAYLAND
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OPENGLES
|
||||
extern const lv_wayland_backend_ops_t wl_egl_ops;
|
||||
extern const lv_wayland_backend_display_ops_t wl_egl_display_ops;
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
|
||||
#if LV_USE_G2D
|
||||
extern const lv_wayland_backend_ops_t wl_g2d_ops,
|
||||
extern const lv_wayland_backend_display_ops_t wl_g2d_display_ops;
|
||||
#endif /*LV_USE_G2D*/
|
||||
|
||||
extern const lv_wayland_backend_ops_t wl_shm_ops;
|
||||
extern const lv_wayland_backend_display_ops_t wl_shm_display_ops;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
const lv_wayland_backend_ops_t * ops;
|
||||
const lv_wayland_backend_display_ops_t * display_ops;
|
||||
void * backend_ctx;
|
||||
} backends[] = {
|
||||
#if LV_USE_OPENGLES
|
||||
{"EGL", &wl_egl_ops, &wl_egl_display_ops, NULL},
|
||||
#endif /*LV_USE_OPENGLES*/
|
||||
#if LV_USE_G2D
|
||||
{"G2D", &wl_g2d_ops, &wl_g2d_display_ops, NULL},
|
||||
#endif /*LV_USE_G2D*/
|
||||
{"SHM", &wl_shm_ops, &wl_shm_display_ops, NULL},
|
||||
};
|
||||
|
||||
const size_t backend_count = (sizeof(backends) / sizeof(backends[0]));
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_wayland_backend_init_all(void)
|
||||
{
|
||||
for(size_t i = 0; i < backend_count; ++i) {
|
||||
LV_LOG_INFO("Initializing '%s' wayland backend", backends[i].name);
|
||||
backends[i].backend_ctx = backends[i].ops->init();
|
||||
}
|
||||
}
|
||||
|
||||
void lv_wayland_backend_deinit_all(void)
|
||||
{
|
||||
for(size_t i = 0; i < backend_count; ++i) {
|
||||
LV_LOG_INFO("Deinitializing '%s' wayland backend", backends[i].name);
|
||||
backends[i].ops->deinit(backends[i].backend_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_wayland_backend_global_handler(struct wl_registry * registry, uint32_t name,
|
||||
const char * interface, uint32_t version)
|
||||
{
|
||||
for(size_t i = 0; i < backend_count; ++i) {
|
||||
backends[i].ops->global_handler(backends[i].backend_ctx, registry, name, interface, version);
|
||||
}
|
||||
}
|
||||
|
||||
lv_result_t lv_wayland_backend_init_display(lv_wayland_backend_display_data_t * backend_ddata,
|
||||
lv_display_t * display,
|
||||
int32_t width,
|
||||
int32_t height)
|
||||
|
||||
{
|
||||
for(size_t i = 0; i < backend_count; ++i) {
|
||||
void * display_data = backends[i].display_ops->init_display(backends[i].backend_ctx, display, width, height);
|
||||
if(!display_data) {
|
||||
LV_LOG_INFO("Failed to initialize display for '%s' wayland backend", backends[i].name);
|
||||
continue;
|
||||
}
|
||||
backend_ddata->ops = backends[i].display_ops;
|
||||
backend_ddata->backend_ctx = backends[i].backend_ctx;
|
||||
backend_ddata->display_data = display_data;
|
||||
LV_LOG_INFO("Initialized display with '%s' wayland backend", backends[i].name);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_WAYLAND*/
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "lv_wayland_private.h"
|
||||
|
||||
#if LV_WAYLAND_USE_EGL
|
||||
#if LV_USE_WAYLAND && LV_USE_OPENGLES
|
||||
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../opengles/lv_opengles_driver.h"
|
||||
@@ -68,10 +68,13 @@ static const struct wl_callback_listener frame_listener = {
|
||||
.done = frame_done,
|
||||
};
|
||||
|
||||
const lv_wayland_backend_ops_t wl_backend_ops = {
|
||||
const lv_wayland_backend_ops_t wl_egl_ops = {
|
||||
.init = wl_egl_init,
|
||||
.deinit = wl_egl_deinit,
|
||||
.global_handler = wl_egl_global_handler,
|
||||
};
|
||||
|
||||
const lv_wayland_backend_display_ops_t wl_egl_display_ops = {
|
||||
.init_display = wl_egl_init_display,
|
||||
.deinit_display = wl_egl_deinit_display,
|
||||
.resize_display = wl_egl_resize_display,
|
||||
@@ -420,4 +423,4 @@ static void wl_egl_flip_cb(void * driver_data, bool vsync)
|
||||
* through wl_surface_commit() which is called in the flush callback */
|
||||
}
|
||||
|
||||
#endif /*LV_WAYLAND_USE_EGL*/
|
||||
#endif /*LV_USE_WAYLAND && LV_USE_OPENGLES*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "lv_wayland_private.h"
|
||||
|
||||
#if LV_WAYLAND_USE_G2D
|
||||
#if LV_USE_WAYLAND && LV_USE_G2D
|
||||
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include <wayland_linux_dmabuf.h>
|
||||
@@ -121,10 +121,13 @@ static lv_wl_buffer_t * get_next_buffer(lv_wl_g2d_display_data_t * ddata);
|
||||
|
||||
static lv_wl_g2d_ctx_t ctx;
|
||||
|
||||
const lv_wayland_backend_ops_t wl_backend_ops = {
|
||||
const lv_wayland_backend_ops_t wl_g2d_ops = {
|
||||
.init = wl_g2d_init,
|
||||
.deinit = wl_g2d_deinit,
|
||||
.global_handler = wl_g2d_global_handler,
|
||||
};
|
||||
|
||||
const lv_wayland_backend_display_ops_t wl_g2d_display_ops = {
|
||||
.init_display = wl_g2d_init_display,
|
||||
.deinit_display = wl_g2d_deinit_display,
|
||||
.resize_display = wl_g2d_resize_display,
|
||||
@@ -644,4 +647,4 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, unsigned char
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_WAYLAND_G2D*/
|
||||
#endif /*LV_USE_WAYLAND && LV_USE_G2D*/
|
||||
|
||||
@@ -136,27 +136,74 @@ typedef void (*lv_wayland_backend_global_handler_t)(void * backend_ctx, struct w
|
||||
* @struct lv_wayland_backend_ops_t
|
||||
* @brief Wayland backend operations structure
|
||||
*
|
||||
* This structure defines the complete set of operations that a Wayland backend
|
||||
* This structure defines the general set of operations that a Wayland backend
|
||||
* must implement. All function pointers must be non-NULL.
|
||||
*
|
||||
* @par Lifecycle Order:
|
||||
* 1. init() - Initialize backend context
|
||||
* 2. global_handler() - Called for each Wayland global (may be called multiple times)
|
||||
* 3. init_display() - Create display (may be called multiple times for multiple displays)
|
||||
* 4. resize_display() - Resize display (called as needed)
|
||||
* 5. deinit_display() - Destroy display (called once per display)
|
||||
* 6. deinit() - Clean up backend context
|
||||
* 3. deinit() - Clean up backend context
|
||||
*/
|
||||
typedef struct {
|
||||
lv_wayland_backend_init_t init; /**< Initialize backend context */
|
||||
lv_wayland_backend_global_handler_t global_handler; /**< Handle Wayland global objects */
|
||||
lv_wayland_backend_init_display_t init_display; /**< Initialize a new display */
|
||||
lv_wayland_backend_resize_display_t resize_display; /**< Resize or reconfigure display */
|
||||
lv_wayland_backend_destroy_display_t deinit_display; /**< Destroy a display */
|
||||
lv_wayland_backend_deinit_t deinit; /**< Deinitialize backend context */
|
||||
} lv_wayland_backend_ops_t;
|
||||
|
||||
extern const lv_wayland_backend_ops_t wl_backend_ops;
|
||||
/**
|
||||
* @struct lv_wayland_backend_display_ops_t
|
||||
* @brief Wayland backend display operations structure
|
||||
*
|
||||
* This structure defines the display specific set of operations that a Wayland backend
|
||||
* must implement. All function pointers must be non-NULL.
|
||||
*
|
||||
* @par Lifecycle Order:
|
||||
* 1. init_display() - Create display (may be called multiple times for multiple displays)
|
||||
* 2. resize_display() - Resize display (called as needed)
|
||||
* 3. deinit_display() - Destroy display (called once per display)
|
||||
*/
|
||||
typedef struct {
|
||||
lv_wayland_backend_init_display_t init_display; /**< Initialize a new display */
|
||||
lv_wayland_backend_resize_display_t resize_display; /**< Resize or reconfigure display */
|
||||
lv_wayland_backend_destroy_display_t deinit_display; /**< Destroy a display */
|
||||
} lv_wayland_backend_display_ops_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
const lv_wayland_backend_display_ops_t * ops; /**< Backend display specific operations */
|
||||
void * backend_ctx; /**< General backend context */
|
||||
void * display_data; /**< Specific display backend data */
|
||||
} lv_wayland_backend_display_data_t;
|
||||
|
||||
/* @brief Initializes all backends
|
||||
*
|
||||
*/
|
||||
void lv_wayland_backend_init_all(void);
|
||||
|
||||
/* @brief Deinitializes all backends
|
||||
*
|
||||
*/
|
||||
void lv_wayland_backend_deinit_all(void);
|
||||
|
||||
/* @brief Deinitializes all backends
|
||||
*
|
||||
*/
|
||||
void lv_wayland_backend_global_handler(struct wl_registry * registry, uint32_t name,
|
||||
const char * interface, uint32_t version);
|
||||
|
||||
/* @brief Loops through all available backends to find one capable of initializing a display
|
||||
*
|
||||
* The function loops through all available backends until it can initialize a display
|
||||
*
|
||||
* @return Pointer to the initialize backend operations or NULL if no backend could be probed
|
||||
*
|
||||
* @note this function does not initialize the backend itself
|
||||
* */
|
||||
|
||||
lv_result_t lv_wayland_backend_init_display(lv_wayland_backend_display_data_t * backend_ddata,
|
||||
lv_display_t * display,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
|
||||
/** @brief Get the backend-specific display data
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "lv_wayland_private.h"
|
||||
|
||||
#if LV_WAYLAND_USE_SHM
|
||||
#if LV_USE_WAYLAND
|
||||
|
||||
#include "../../draw/sw/lv_draw_sw_utils.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
@@ -87,10 +87,13 @@ static const struct wl_buffer_listener buffer_listener = {
|
||||
.release = buffer_release
|
||||
};
|
||||
|
||||
const lv_wayland_backend_ops_t wl_backend_ops = {
|
||||
const lv_wayland_backend_ops_t wl_shm_ops = {
|
||||
.init = shm_init,
|
||||
.deinit = shm_deinit,
|
||||
.global_handler = shm_global_handler,
|
||||
};
|
||||
|
||||
const lv_wayland_backend_display_ops_t wl_shm_display_ops = {
|
||||
.init_display = shm_init_display,
|
||||
.deinit_display = shm_deinit_display,
|
||||
.resize_display = shm_resize_display,
|
||||
@@ -454,4 +457,4 @@ static void shm_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t *
|
||||
ddata->curr_wl_buffer_idx = (ddata->curr_wl_buffer_idx + 1) % LV_WL_SHM_BUF_COUNT;
|
||||
}
|
||||
|
||||
#endif /*LV_WAYLAND_USE_SHM*/
|
||||
#endif /*LV_USE_WAYLAND*/
|
||||
|
||||
@@ -99,7 +99,6 @@ typedef struct {
|
||||
struct wl_shm * wl_shm;
|
||||
lv_wl_seat_t seat;
|
||||
|
||||
void * backend_data;
|
||||
lv_wl_output_info_t physical_outputs[LV_WAYLAND_MAX_OUTPUTS];
|
||||
uint8_t wl_output_count;
|
||||
|
||||
@@ -126,12 +125,12 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct _lv_wl_window_t {
|
||||
void * backend_display_data;
|
||||
lv_display_t * lv_disp;
|
||||
lv_indev_t * lv_indev_pointer;
|
||||
lv_indev_t * lv_indev_pointeraxis;
|
||||
lv_indev_t * lv_indev_touch;
|
||||
lv_indev_t * lv_indev_keyboard;
|
||||
lv_wayland_backend_display_data_t backend_ddata;
|
||||
lv_wayland_display_close_cb_t close_cb;
|
||||
lv_wl_window_xdg_t xdg;
|
||||
|
||||
|
||||
@@ -90,7 +90,16 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char
|
||||
lv_display_set_driver_data(window->lv_disp, window);
|
||||
|
||||
/* Initialize display driver */
|
||||
window->backend_display_data = wl_backend_ops.init_display(lv_wl_ctx.backend_data, window->lv_disp, hor_res, ver_res);
|
||||
lv_result_t res = lv_wayland_backend_init_display(&window->backend_ddata,
|
||||
window->lv_disp, hor_res,
|
||||
ver_res);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Failed to create display");
|
||||
goto init_display_err;
|
||||
}
|
||||
|
||||
/*Assert here so tat we can freely use these operations afterwards*/
|
||||
LV_ASSERT_NULL(window->backend_ddata.ops);
|
||||
|
||||
lv_wayland_xdg_configure_surface(window);
|
||||
|
||||
@@ -128,7 +137,8 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char
|
||||
LV_LOG_ERROR("failed to register keyboard indev");
|
||||
}
|
||||
return window->lv_disp;
|
||||
|
||||
init_display_err:
|
||||
lv_wayland_xdg_delete_window(&window->xdg);
|
||||
create_window_err:
|
||||
wl_surface_destroy(window->body);
|
||||
create_surface_err:
|
||||
@@ -145,7 +155,7 @@ void * lv_wayland_get_backend_display_data(lv_display_t * display)
|
||||
LV_ASSERT_NULL(display);
|
||||
lv_wl_window_t * window = lv_display_get_driver_data(display);
|
||||
LV_ASSERT_NULL(window);
|
||||
return window->backend_display_data;
|
||||
return window->backend_ddata.display_data;
|
||||
}
|
||||
|
||||
void lv_wayland_set_backend_display_data(lv_display_t * display, void * data)
|
||||
@@ -153,7 +163,7 @@ 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;
|
||||
window->backend_ddata.display_data = data;
|
||||
}
|
||||
|
||||
struct wl_surface * lv_wayland_get_window_surface(lv_display_t * display)
|
||||
@@ -289,8 +299,7 @@ void lv_wayland_window_delete(lv_wl_window_t * window)
|
||||
/* Make sure buffer is correctly released*/
|
||||
wl_display_roundtrip(lv_wl_ctx.wl_display);
|
||||
|
||||
wl_backend_ops.deinit_display(window->backend_display_data, window->lv_disp);
|
||||
window->backend_display_data = NULL;
|
||||
window->backend_ddata.ops->deinit_display(window->backend_ddata.backend_ctx, window->lv_disp);
|
||||
|
||||
/* Set the driver data to NULL before calling display delete
|
||||
* so that the delete event doesn't do anything*/
|
||||
@@ -338,7 +347,9 @@ static void res_changed_event(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * display = (lv_display_t *) lv_event_get_target(e);
|
||||
lv_wl_window_t * window = lv_display_get_driver_data(display);
|
||||
window->backend_display_data = wl_backend_ops.resize_display(lv_wl_ctx.backend_data, display);
|
||||
|
||||
window->backend_ddata.display_data = window->backend_ddata.ops->resize_display(window->backend_ddata.backend_ctx,
|
||||
display);
|
||||
}
|
||||
|
||||
#endif /* LV_USE_WAYLAND */
|
||||
|
||||
+6
-21
@@ -4861,27 +4861,6 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#define LV_LOG_TRACE_ANIM 0
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
#if LV_USE_WAYLAND
|
||||
/*Automatically detect wayland backend*/
|
||||
#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_SHM 0
|
||||
#else
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#define LV_WAYLAND_USE_G2D 0
|
||||
#define LV_WAYLAND_USE_SHM 1
|
||||
#endif
|
||||
#else
|
||||
#define LV_WAYLAND_USE_G2D 0
|
||||
#define LV_WAYLAND_USE_SHM 0
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#if LV_USE_LINUX_DRM
|
||||
#if LV_USE_OPENGLES
|
||||
#define LV_LINUX_DRM_USE_EGL 1
|
||||
@@ -4940,6 +4919,12 @@ LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN);
|
||||
#define LV_SDL_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#if LV_USE_WAYLAND && LV_USE_OPENGLES
|
||||
#define LV_WAYLAND_USE_EGL 1
|
||||
#else
|
||||
#define LV_WAYLAND_USE_EGL 0
|
||||
#endif
|
||||
|
||||
#ifndef LV_USE_EGL
|
||||
#if LV_LINUX_DRM_USE_EGL || LV_WAYLAND_USE_EGL || LV_SDL_USE_EGL
|
||||
#define LV_USE_EGL 1
|
||||
|
||||
Reference in New Issue
Block a user