mirror of
https://github.com/lvgl/lvgl.git
synced 2026-08-17 18:22:42 +08:00
feat(wayland): add DMA-BUF software fast-path to the EGL backend (#10339)
Signed-off-by: Sang Tran <sang.tran.jc@renesas.com> Signed-off-by: Vu Dang <vu.dang.te@renesas.com>
This commit is contained in:
@@ -2775,9 +2775,14 @@ config LV_WAYLAND_USE_SHM
|
||||
config LV_WAYLAND_USE_EGL
|
||||
bool
|
||||
select LV_USE_EGL
|
||||
select LV_WAYLAND_USE_DMABUF if !LV_USE_DRAW_OPENGLES && !LV_USE_DRAW_NANOVG
|
||||
|
||||
config LV_WAYLAND_USE_G2D
|
||||
bool
|
||||
select LV_WAYLAND_USE_DMABUF
|
||||
|
||||
config LV_WAYLAND_USE_DMABUF
|
||||
bool
|
||||
|
||||
endif # LV_USE_WAYLAND
|
||||
config LV_USE_WINDOWS
|
||||
|
||||
@@ -71,13 +71,26 @@ enabling GPU-accelerated graphics on Wayland compositors that support the necess
|
||||
|
||||
To enable the EGL backend:
|
||||
|
||||
1. Enable OpenGL ES support in your LVGL configuration:
|
||||
1. Select the EGL backend explicitly. `LV_WAYLAND_AUTO_BACKEND` defaults to `1`, in
|
||||
which case the driver falls back to the SHM backend unless a backend is
|
||||
selected; set it to `0` and pick `LV_WAYLAND_BACKEND_EGL`:
|
||||
|
||||
```c
|
||||
#define LV_WAYLAND_AUTO_BACKEND 0
|
||||
#define LV_WAYLAND_BACKEND LV_WAYLAND_BACKEND_EGL
|
||||
```
|
||||
|
||||
If you configure LVGL through Kconfig/menuconfig instead of `lv_conf.h`, pick
|
||||
the **EGL (OpenGL ES, hardware-accelerated)** option under the Wayland driver's
|
||||
"Rendering backend" choice instead.
|
||||
|
||||
2. Enable OpenGL ES support in your LVGL configuration:
|
||||
|
||||
```c
|
||||
#define LV_USE_OPENGLES 1
|
||||
```
|
||||
|
||||
2. Link your application with the `wayland-egl` library (add to your build system):
|
||||
3. Link your application with the `wayland-egl` library (add to your build system):
|
||||
|
||||
```bash
|
||||
-lwayland-egl
|
||||
@@ -86,6 +99,32 @@ To enable the EGL backend:
|
||||
**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 [3D/glTF Support](/integration/embedded_linux/opengl) for details on 3D rendering support.
|
||||
|
||||
#### DMA-BUF Software Fast-Path
|
||||
|
||||
When the EGL backend is used for software rendering, it automatically uses the
|
||||
Linux DMA-BUF protocol to present frames, improving performance on platforms
|
||||
that support zero-copy buffer sharing. If the required support is unavailable,
|
||||
the backend automatically falls back to the classic software path.
|
||||
|
||||
**Requirements:**
|
||||
|
||||
- A Wayland compositor with `zwp_linux_dmabuf_v1` support
|
||||
- GPU/display driver support for DMA-BUF
|
||||
- EGL/OpenGL ES support
|
||||
- `libdrm` and `gbm` (used to allocate the shared buffers)
|
||||
- The `linux-dmabuf` Wayland protocol generated at build time
|
||||
|
||||
When building with LVGL's CMake build system, the `linux-dmabuf` protocol is
|
||||
generated and `libdrm`/`gbm` are resolved automatically — no extra steps are
|
||||
needed. For other build systems, generate the `linux-dmabuf` protocol with
|
||||
`wayland-scanner` and link the additional libraries:
|
||||
|
||||
```bash
|
||||
-lwayland-egl
|
||||
-ldrm
|
||||
-lgbm
|
||||
```
|
||||
|
||||
### G2D Backend
|
||||
|
||||
The G2D backend leverages NXP's hardware-accelerated 2D graphics engine available on i.MX processors. This backend provides improved performance on NXP platforms.
|
||||
@@ -236,7 +275,9 @@ wayland-scanner client-header $SYSROOT/usr/share/wayland-protocols/stable/xdg-sh
|
||||
wayland-scanner private-code $SYSROOT/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml wayland_xdg_shell.c
|
||||
```
|
||||
|
||||
When `LV_WAYLAND_USE_DMABUF` is set to `1`, the following protocols must also be generated:
|
||||
When using the [G2D backend](#g2d-backend), or the [EGL backend](#egl-backend)'s
|
||||
[DMA-BUF software fast-path](#dma-buf-software-fast-path), the following protocols
|
||||
must also be generated:
|
||||
|
||||
```sh
|
||||
wayland-scanner client-header $SYSROOT/usr/share/wayland-protocols/stable/linux-dmabuf/linux-dmabuf-v1.xml wayland_linux_dmabuf.h
|
||||
|
||||
@@ -33,11 +33,12 @@ if(CONFIG_LV_USE_SDL)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/dependencies/sdl2.cmake)
|
||||
endif()
|
||||
|
||||
if(CONFIG_LV_USE_LINUX_DRM)
|
||||
if(CONFIG_LV_USE_LINUX_DRM OR CONFIG_LV_WAYLAND_USE_DMABUF)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/dependencies/drm.cmake)
|
||||
endif()
|
||||
|
||||
if(CONFIG_LV_USE_LINUX_DRM_GBM_BUFFERS OR CONFIG_LV_LINUX_DRM_USE_EGL)
|
||||
if(CONFIG_LV_USE_LINUX_DRM_GBM_BUFFERS OR CONFIG_LV_LINUX_DRM_USE_EGL OR
|
||||
(CONFIG_LV_WAYLAND_USE_EGL AND CONFIG_LV_WAYLAND_USE_DMABUF))
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/dependencies/gbm.cmake)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -150,8 +150,8 @@ endif()
|
||||
|
||||
set(WAYLAND_PROTOCOL_SOURCES ${XDG_SHELL_SOURCE})
|
||||
|
||||
# dmabuf (optional)
|
||||
if(CONFIG_LV_WAYLAND_USE_G2D)
|
||||
# dmabuf (optional) - used by the G2D backend and by the Wayland EGL DMA-BUF fast-path
|
||||
if(CONFIG_LV_WAYLAND_USE_DMABUF)
|
||||
set(DMABUF_XML "${PROTOCOL_ROOT}/stable/linux-dmabuf/linux-dmabuf-v1.xml")
|
||||
set(DMABUF_HEADER "${PROTOCOLS_DIR}/wayland_linux_dmabuf.h")
|
||||
set(DMABUF_SOURCE "${PROTOCOLS_DIR}/wayland_linux_dmabuf.c")
|
||||
|
||||
@@ -4926,6 +4926,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LV_WAYLAND_USE_DMABUF
|
||||
#if (((LV_WAYLAND_USE_EGL && !LV_USE_DRAW_OPENGLES && !LV_USE_DRAW_NANOVG && LV_USE_WAYLAND) || (LV_WAYLAND_USE_G2D && LV_USE_WAYLAND)) && (LV_USE_WAYLAND))
|
||||
#define LV_WAYLAND_USE_DMABUF 1
|
||||
#else
|
||||
#define LV_WAYLAND_USE_DMABUF 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Optional user headers (LV_*_USE_CUSTOM_INCLUDE) overriding config macros. */
|
||||
#if LV_OS_USE_CUSTOM_INCLUDE
|
||||
#include LV_OS_CUSTOM_INCLUDE
|
||||
|
||||
@@ -110,6 +110,7 @@ ALLOWED_EXTERNAL_HEADERS: set[str] = {
|
||||
"GL/glew.h",
|
||||
"GLES2/gl2.h",
|
||||
"GLES2/gl2ext.h",
|
||||
"GLES2/gl2platform.h",
|
||||
"GLES3/gl3.h",
|
||||
"GLFW/glfw3.h",
|
||||
"LGFX_AUTODETECT.hpp",
|
||||
|
||||
@@ -64,8 +64,13 @@ config LV_WAYLAND_USE_SHM
|
||||
config LV_WAYLAND_USE_EGL
|
||||
bool
|
||||
select LV_USE_EGL
|
||||
select LV_WAYLAND_USE_DMABUF if !LV_USE_DRAW_OPENGLES && !LV_USE_DRAW_NANOVG
|
||||
|
||||
config LV_WAYLAND_USE_G2D
|
||||
bool
|
||||
select LV_WAYLAND_USE_DMABUF
|
||||
|
||||
config LV_WAYLAND_USE_DMABUF
|
||||
bool
|
||||
|
||||
endif # LV_USE_WAYLAND
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,337 @@
|
||||
/**
|
||||
* @file lv_wayland_dmabuf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_wayland_dmabuf.h"
|
||||
|
||||
#if LV_USE_WAYLAND && LV_WAYLAND_USE_DMABUF
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <wayland_linux_dmabuf.h>
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void dmabuf_done(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback);
|
||||
static void dmabuf_format_table(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
int32_t fd, uint32_t size);
|
||||
static void dmabuf_main_device(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * device);
|
||||
static void dmabuf_tranche_done(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback);
|
||||
static void dmabuf_tranche_target_device(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * device);
|
||||
static void dmabuf_tranche_formats(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * indices);
|
||||
static void dmabuf_tranche_flags(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
uint32_t flags);
|
||||
static void dmabuf_modifiers(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format,
|
||||
uint32_t modifier_hi, uint32_t modifier_lo);
|
||||
static void dmabuf_format(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format);
|
||||
|
||||
static void buffer_release(void * data, struct wl_buffer * buffer);
|
||||
static void create_succeeded(void * data, struct zwp_linux_buffer_params_v1 * params, struct wl_buffer * new_buffer);
|
||||
static void create_failed(void * data, struct zwp_linux_buffer_params_v1 * params);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_listener_v5 = {
|
||||
.done = dmabuf_done,
|
||||
.format_table = dmabuf_format_table,
|
||||
.main_device = dmabuf_main_device,
|
||||
.tranche_done = dmabuf_tranche_done,
|
||||
.tranche_target_device = dmabuf_tranche_target_device,
|
||||
.tranche_formats = dmabuf_tranche_formats,
|
||||
.tranche_flags = dmabuf_tranche_flags,
|
||||
};
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener_v3 = {
|
||||
.format = dmabuf_format,
|
||||
.modifier = dmabuf_modifiers
|
||||
};
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
|
||||
.format = dmabuf_format
|
||||
};
|
||||
|
||||
static const struct zwp_linux_buffer_params_v1_listener params_listener = {
|
||||
.created = create_succeeded,
|
||||
.failed = create_failed
|
||||
};
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
.release = buffer_release
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_wayland_dmabuf_ctx_init(lv_wayland_dmabuf_ctx_t * ctx)
|
||||
{
|
||||
lv_memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
void lv_wayland_dmabuf_ctx_deinit(lv_wayland_dmabuf_ctx_t * ctx)
|
||||
{
|
||||
if(!ctx) {
|
||||
return;
|
||||
}
|
||||
if(ctx->feedback) {
|
||||
zwp_linux_dmabuf_feedback_v1_destroy(ctx->feedback);
|
||||
ctx->feedback = NULL;
|
||||
}
|
||||
if(ctx->handler) {
|
||||
zwp_linux_dmabuf_v1_destroy(ctx->handler);
|
||||
ctx->handler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_wayland_dmabuf_registry_handle_global(lv_wayland_dmabuf_ctx_t * ctx, struct wl_registry * registry,
|
||||
uint32_t name, const char * interface, uint32_t version)
|
||||
{
|
||||
if(!lv_streq(interface, zwp_linux_dmabuf_v1_interface.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
version = LV_MIN(version, (uint32_t)zwp_linux_dmabuf_v1_interface.version);
|
||||
ctx->handler = wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, version);
|
||||
|
||||
if(version >= 4) {
|
||||
ctx->feedback = zwp_linux_dmabuf_v1_get_default_feedback(ctx->handler);
|
||||
zwp_linux_dmabuf_feedback_v1_add_listener(ctx->feedback, &dmabuf_listener_v5, ctx);
|
||||
}
|
||||
else if(version < 3) {
|
||||
zwp_linux_dmabuf_v1_add_listener(ctx->handler, &dmabuf_listener, ctx);
|
||||
}
|
||||
else if(version == 3) {
|
||||
zwp_linux_dmabuf_v1_add_listener(ctx->handler, &dmabuf_listener_v3, ctx);
|
||||
}
|
||||
wl_display_roundtrip(lv_wl_ctx.wl_display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t lv_wayland_dmabuf_cf_to_drm(lv_color_format_t cf)
|
||||
{
|
||||
if(cf == LV_COLOR_FORMAT_UNKNOWN) {
|
||||
return DRM_FORMAT_ARGB8888; /* Default to ARGB8888 */
|
||||
}
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
return DRM_FORMAT_XRGB8888;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED:
|
||||
return DRM_FORMAT_ARGB8888;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
return DRM_FORMAT_RGB565;
|
||||
default:
|
||||
return DRM_FORMAT_ARGB8888;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_wayland_dmabuf_create_buffer(lv_wayland_dmabuf_ctx_t * ctx, lv_wayland_dmabuf_buffer_t * buf,
|
||||
int dmabuf_fd, uint32_t width, uint32_t height,
|
||||
uint32_t stride, uint32_t offset, uint32_t drm_cf)
|
||||
{
|
||||
/* Will be set on the create callback if the creation is successful */
|
||||
buf->wl_buffer = NULL;
|
||||
|
||||
struct zwp_linux_buffer_params_v1 * params = zwp_linux_dmabuf_v1_create_params(ctx->handler);
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, dmabuf_fd, 0, offset, stride, 0, 0);
|
||||
|
||||
zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, buf);
|
||||
zwp_linux_buffer_params_v1_create(params, width, height, drm_cf, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void buffer_release(void * data, struct wl_buffer * buffer)
|
||||
{
|
||||
LV_LOG_TRACE("Buffer released");
|
||||
LV_UNUSED(buffer);
|
||||
lv_wayland_dmabuf_buffer_t * buf = data;
|
||||
buf->busy = false;
|
||||
}
|
||||
|
||||
static void create_succeeded(void * data, struct zwp_linux_buffer_params_v1 * params, struct wl_buffer * new_buffer)
|
||||
{
|
||||
LV_LOG_TRACE("Buffer created successfully");
|
||||
lv_wayland_dmabuf_buffer_t * buf = data;
|
||||
buf->wl_buffer = new_buffer;
|
||||
|
||||
/* When not using explicit synchronization listen to wl_buffer.release
|
||||
* for release notifications, otherwise we are going to use
|
||||
* zwp_linux_buffer_release_v1. */
|
||||
wl_buffer_add_listener(buf->wl_buffer, &buffer_listener, buf);
|
||||
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
}
|
||||
|
||||
static void create_failed(void * data, struct zwp_linux_buffer_params_v1 * params)
|
||||
{
|
||||
lv_wayland_dmabuf_buffer_t * buf = data;
|
||||
buf->wl_buffer = NULL;
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
LV_LOG_ERROR("Failed to create dmabuf buffer");
|
||||
}
|
||||
|
||||
static void dmabuf_format_table(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
int32_t fd, uint32_t size)
|
||||
{
|
||||
lv_wayland_dmabuf_ctx_t * ctx = data;
|
||||
|
||||
LV_UNUSED(feedback);
|
||||
|
||||
if(fd < 0 || size == 0) {
|
||||
LV_LOG_ERROR("Invalid format table fd=%d size=%u", fd, size);
|
||||
if(fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map the format table file descriptor */
|
||||
void * table = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if(table == MAP_FAILED) {
|
||||
LV_LOG_ERROR("Failed to mmap format table: %s", strerror(errno));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("Received format table with fd %d and size %u", fd, size);
|
||||
|
||||
/* Parse the format table - each entry is 16 bytes: 4 bytes format + 4 bytes padding + 8 bytes modifier */
|
||||
size_t num_formats = size / 16;
|
||||
uint32_t * formats = (uint32_t *)table;
|
||||
|
||||
for(size_t i = 0; i < num_formats; i++) {
|
||||
/* Each entry is 4 uint32_t words */
|
||||
uint32_t format = formats[i * 4];
|
||||
if(format == DRM_FORMAT_RGB565) {
|
||||
ctx->supports_rgb565 = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
munmap(table, size);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void dmabuf_done(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
|
||||
LV_LOG_TRACE("DMABUF feedback done");
|
||||
|
||||
/* This event marks the end of a feedback round. The client has received
|
||||
* all the format and modifier pairs from all tranches. This allows
|
||||
* the client to proceed with buffer allocation. */
|
||||
}
|
||||
|
||||
static void dmabuf_main_device(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * device)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
LV_UNUSED(device);
|
||||
|
||||
LV_LOG_TRACE("DMABUF main device received (size: %zu)", device->size);
|
||||
|
||||
/* This event advertises the main device that the server-side allocator
|
||||
* will use for scanout. It should be used by clients as a hint for
|
||||
* buffer allocation. */
|
||||
}
|
||||
|
||||
static void dmabuf_tranche_done(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
|
||||
LV_LOG_TRACE("DMABUF tranche done");
|
||||
|
||||
/* This event marks the end of a tranche. This allows the client to
|
||||
* process the formats and modifiers it has received for this tranche. */
|
||||
}
|
||||
|
||||
static void dmabuf_tranche_target_device(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * device)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
LV_UNUSED(device);
|
||||
|
||||
LV_LOG_TRACE("DMABUF tranche target device (size: %zu)", device->size);
|
||||
|
||||
/* This event advertises the target device that the following tranche
|
||||
* will apply to. */
|
||||
}
|
||||
|
||||
static void dmabuf_tranche_formats(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
struct wl_array * indices)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
|
||||
LV_LOG_TRACE("DMABUF tranche formats (count: %zu)", indices->size / sizeof(uint16_t));
|
||||
|
||||
/* This event advertises the format + modifier pairs that the compositor
|
||||
* supports for the current tranche. The indices are offsets into the
|
||||
* format table sent earlier. */
|
||||
|
||||
if(indices->size > 0) {
|
||||
/* If we don't have a format yet, we could parse the indices here
|
||||
* to find a suitable format from the format table, but for now
|
||||
* we rely on the format_table callback to set a format directly */
|
||||
LV_LOG_TRACE("Format indices received");
|
||||
}
|
||||
}
|
||||
|
||||
static void dmabuf_tranche_flags(void * data, struct zwp_linux_dmabuf_feedback_v1 * feedback,
|
||||
uint32_t flags)
|
||||
{
|
||||
LV_UNUSED(data);
|
||||
LV_UNUSED(feedback);
|
||||
LV_UNUSED(flags);
|
||||
|
||||
LV_LOG_TRACE("DMABUF tranche flags: 0x%x", flags);
|
||||
|
||||
/* This event advertises the flags for the current tranche.
|
||||
* Flags can indicate special properties like scanout support. */
|
||||
}
|
||||
|
||||
static void dmabuf_modifiers(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format,
|
||||
uint32_t modifier_hi, uint32_t modifier_lo)
|
||||
{
|
||||
LV_UNUSED(modifier_hi);
|
||||
LV_UNUSED(modifier_lo);
|
||||
dmabuf_format(data, zwp_linux_dmabuf, format);
|
||||
}
|
||||
|
||||
static void dmabuf_format(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format)
|
||||
{
|
||||
lv_wayland_dmabuf_ctx_t * ctx = data;
|
||||
|
||||
LV_UNUSED(zwp_linux_dmabuf);
|
||||
if(format == DRM_FORMAT_RGB565) {
|
||||
ctx->supports_rgb565 = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_WAYLAND && LV_WAYLAND_USE_DMABUF*/
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @file lv_wayland_dmabuf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_WAYLAND_DMABUF_H
|
||||
#define LV_WAYLAND_DMABUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_wayland_private.h"
|
||||
|
||||
#if LV_USE_WAYLAND && LV_WAYLAND_USE_DMABUF
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include LV_STDBOOL_INCLUDE
|
||||
#include LV_STDINT_INCLUDE
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Shared DMA-BUF protocol context.
|
||||
*
|
||||
* Holds the bound zwp_linux_dmabuf_v1 object and the capabilities detected
|
||||
* during the feedback/format negotiation. One instance per backend is enough;
|
||||
* it is created in the backend's init() and used as its backend context.
|
||||
*/
|
||||
typedef struct {
|
||||
struct zwp_linux_dmabuf_v1 * handler; /**< Bound protocol object, NULL if unavailable */
|
||||
struct zwp_linux_dmabuf_feedback_v1 * feedback; /**< Default feedback proxy, NULL if unused (protocol < 4) */
|
||||
bool supports_rgb565; /**< XRGB8888 / ARGB8888 are always supported */
|
||||
} lv_wayland_dmabuf_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Per-buffer DMA-BUF protocol state.
|
||||
*
|
||||
* A backend embeds this in its own buffer structure and adds the
|
||||
* allocator-specific fields (e.g. a gbm_bo + EGLImage, or an lv_draw_buf).
|
||||
* The release tracking (@ref busy) and the wl_buffer lifetime are managed
|
||||
* through this struct by the shared helper.
|
||||
*/
|
||||
typedef struct {
|
||||
struct wl_buffer * wl_buffer; /**< Created asynchronously; NULL until ready or on failure */
|
||||
bool busy; /**< true while the compositor still owns the buffer */
|
||||
} lv_wayland_dmabuf_buffer_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Reset a DMA-BUF context to a clean state.
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void lv_wayland_dmabuf_ctx_init(lv_wayland_dmabuf_ctx_t * ctx);
|
||||
|
||||
/**
|
||||
* @brief Release the resources held by a DMA-BUF context.
|
||||
* @param ctx context to deinitialize
|
||||
*/
|
||||
void lv_wayland_dmabuf_ctx_deinit(lv_wayland_dmabuf_ctx_t * ctx);
|
||||
|
||||
/**
|
||||
* @brief Handle a wl_registry global announcement.
|
||||
*
|
||||
* Binds the zwp_linux_dmabuf_v1 interface and starts the format/feedback
|
||||
* negotiation when the matching global is advertised.
|
||||
*
|
||||
* @param ctx DMA-BUF context
|
||||
* @param registry the wl_registry
|
||||
* @param name numeric name of the global
|
||||
* @param interface interface string
|
||||
* @param version advertised interface version
|
||||
* @return true if this global was the dmabuf interface and was handled
|
||||
*/
|
||||
bool lv_wayland_dmabuf_registry_handle_global(lv_wayland_dmabuf_ctx_t * ctx, struct wl_registry * registry,
|
||||
uint32_t name, const char * interface, uint32_t version);
|
||||
|
||||
/**
|
||||
* @brief Convert an LVGL color format to a DRM fourcc code.
|
||||
* @param cf LVGL color format
|
||||
* @return the matching DRM_FORMAT_* code (defaults to ARGB8888)
|
||||
*/
|
||||
uint32_t lv_wayland_dmabuf_cf_to_drm(lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* @brief Create a wl_buffer from a DMA-BUF file descriptor.
|
||||
*
|
||||
* Wraps the zwp_linux_buffer_params_v1 sequence. The resulting wl_buffer is
|
||||
* delivered asynchronously into @p buf->wl_buffer, so the caller must perform a
|
||||
* wl_display roundtrip and then verify that @p buf->wl_buffer is non-NULL. The
|
||||
* buffer's release listener clears @p buf->busy when the compositor is done.
|
||||
*
|
||||
* @param ctx DMA-BUF context
|
||||
* @param buf per-buffer protocol state (embedded in the backend buffer)
|
||||
* @param dmabuf_fd the DMA-BUF file descriptor to share
|
||||
* @param width buffer width in pixels
|
||||
* @param height buffer height in pixels
|
||||
* @param stride row stride in bytes
|
||||
* @param offset plane offset in bytes
|
||||
* @param drm_cf DRM fourcc of the buffer
|
||||
*/
|
||||
void lv_wayland_dmabuf_create_buffer(lv_wayland_dmabuf_ctx_t * ctx, lv_wayland_dmabuf_buffer_t * buf,
|
||||
int dmabuf_fd, uint32_t width, uint32_t height,
|
||||
uint32_t stride, uint32_t offset, uint32_t drm_cf);
|
||||
|
||||
#endif /*LV_USE_WAYLAND && LV_WAYLAND_USE_DMABUF*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_WAYLAND_DMABUF_H*/
|
||||
@@ -121,6 +121,7 @@
|
||||
#include "drivers/sdl/lv_sdl_private.h"
|
||||
#include "drivers/uefi/lv_uefi_private.h"
|
||||
#include "drivers/wayland/lv_wayland_backend_private.h"
|
||||
#include "drivers/wayland/lv_wayland_dmabuf.h"
|
||||
#include "drivers/wayland/lv_wayland_private.h"
|
||||
#include "drivers/windows/lv_windows_context.h"
|
||||
#include "drivers/windows/lv_windows_input_private.h"
|
||||
|
||||
Reference in New Issue
Block a user