diff --git a/scripts/lv_conf_internal_gen.py b/scripts/lv_conf_internal_gen.py index f48a8df718..732b7de5d9 100755 --- a/scripts/lv_conf_internal_gen.py +++ b/scripts/lv_conf_internal_gen.py @@ -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 diff --git a/src/drivers/wayland/lv_wayland.c b/src/drivers/wayland/lv_wayland.c index 338233b517..bc5c7b16d6 100644 --- a/src/drivers/wayland/lv_wayland.c +++ b/src/drivers/wayland/lv_wayland.c @@ -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) diff --git a/src/drivers/wayland/lv_wayland_backend.c b/src/drivers/wayland/lv_wayland_backend.c new file mode 100644 index 0000000000..90c46b3b88 --- /dev/null +++ b/src/drivers/wayland/lv_wayland_backend.c @@ -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*/ diff --git a/src/drivers/wayland/lv_wayland_backend_egl.c b/src/drivers/wayland/lv_wayland_backend_egl.c index 542577f3f4..ef1c84874f 100644 --- a/src/drivers/wayland/lv_wayland_backend_egl.c +++ b/src/drivers/wayland/lv_wayland_backend_egl.c @@ -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*/ diff --git a/src/drivers/wayland/lv_wayland_backend_g2d.c b/src/drivers/wayland/lv_wayland_backend_g2d.c index 69cc67c7c7..230fd25a57 100644 --- a/src/drivers/wayland/lv_wayland_backend_g2d.c +++ b/src/drivers/wayland/lv_wayland_backend_g2d.c @@ -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 @@ -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*/ diff --git a/src/drivers/wayland/lv_wayland_backend_private.h b/src/drivers/wayland/lv_wayland_backend_private.h index c9e617b79f..b1fa57ae9c 100644 --- a/src/drivers/wayland/lv_wayland_backend_private.h +++ b/src/drivers/wayland/lv_wayland_backend_private.h @@ -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 * diff --git a/src/drivers/wayland/lv_wayland_backend_shm.c b/src/drivers/wayland/lv_wayland_backend_shm.c index ca657c4fc5..e7a0429cd0 100644 --- a/src/drivers/wayland/lv_wayland_backend_shm.c +++ b/src/drivers/wayland/lv_wayland_backend_shm.c @@ -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*/ diff --git a/src/drivers/wayland/lv_wayland_private.h b/src/drivers/wayland/lv_wayland_private.h index c51ae7e3a1..f4aa6ff525 100644 --- a/src/drivers/wayland/lv_wayland_private.h +++ b/src/drivers/wayland/lv_wayland_private.h @@ -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; diff --git a/src/drivers/wayland/lv_wayland_window.c b/src/drivers/wayland/lv_wayland_window.c index 1799354444..0e7b6e6d4d 100644 --- a/src/drivers/wayland/lv_wayland_window.c +++ b/src/drivers/wayland/lv_wayland_window.c @@ -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 */ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 0c89315063..91cd41ea41 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -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