Weston (Wayland) 窗口系统
Wayland 是一种显示服务器与其客户端之间通信的协议。Wayland 服务器使用 Wayland 协议与 GUI 程序(即 Wayland 客户端)通信。Wayland 服务器也称为 Wayland 合成器,因为它也充当合成窗口管理器。
Weston 服务器,通常简称为 Weston,是 Wayland 合成器的参考实现。它管理显示器,包括其内容的合成、对其输入设备事件(触摸屏、鼠标、键盘等)的支持以及其设置(壁纸、分辨率、多显示器显示等)。
与 X11 相比,Weston 更轻量级,并且作为合成器速度很快。它适用于许多嵌入式和移动用例。
当前版本的 Jetson Linux 支持 Weston 6.0。
Weston/Wayland 架构
Wayland 服务器和一组 Weston 库统称为 Weston/Wayland。此图描述了 Weston/Wayland 架构。
Wayland 服务器库实现了 Weston 的 Wayland 协议。Weston 库实现了 Wayland 合成器,它使用 Linux 内核模式设置 (KMS) 来设置显示,使用
OpenGLES 和
直接渲染管理器 (DRM) 执行合成,并管理 Linux 输入设备。
Wayland 客户端应用程序使用 Wayland 协议与 Wayland 合成器通信。它可能是 EGL 应用程序、X 服务器(无根)或其他类型的显示服务器。
Shells
Weston 通过 shell 插件支持不同的图形用户界面。NVIDIA 发行版 Weston 带有两个插件:桌面 shell 和 IVI shell。
桌面和 IVI shell 各自为 Wayland 客户端提供自己的 Wayland 协议接口。因此,为特定 shell 协议编写的 Wayland 客户端不适用于其他 shell 协议。
桌面 shell 提供类似于 X11 的现代桌面环境,以及键盘和鼠标的接口。它由库 desktop-shell.so 实现。一个特殊的桌面 shell 客户端 weston-desktop-shell 渲染壁纸、面板和其他桌面元素。
IVI shell 专为车载信息娱乐 (IVI) 应用程序设计。它通过其控制器模块提供与 GENIVI Layer Manager 兼容的 API,以及供 IVI 应用程序使用的简单协议。它由库 ivi-shell.so 实现。
配置
您可以通过配置文件 /etc/xdg/weston/weston.ini 配置 Weston shell 的外观和行为偏好设置。
有关配置 Weston shell 的更多信息,请参阅
Ubuntu weston.ini 手册页。
环境变量
Weston 使用的环境变量有
• WAYLAND_DEBUG:如果设置为任何值,则会导致 libwayland 将实时协议打印到 stderr。
• XDG_RUNTIME_DIR:指定 Weston 的套接字和锁定文件的目录。如果设置,Weston 将在此目录下创建其套接字,Wayland 客户端使用此目录下的套接字与 Weston 通信。
运行 Weston 6.0
使用以下步骤启动 Weston。
启动 Weston
1. 如果 X 服务器正在运行,请停止它
$ sudo service gdm stop; sudo pkill -9 Xorg
2. 启动 Tegra 虚拟 DRM 驱动程序
$ sudo modprobe tegra-udrm modeset=1
3. 创建 libgbm.so.1 符号链接
$ sudo ln -sf /usr/lib/aarch64-linux-gnu/tegra/libnvgbm.so /usr/lib/aarch64-linux-gnu/libgbm.so.1
4. 设置环境和目录权限
$ unset DISPLAY
$ mkdir /tmp/xdg
$ chmod 700 /tmp/xdg
5. 选择有效的 TTY 设备
$ export WESTON_TTY=1
6. 启动 Weston。
1. 要以 root 用户身份启动 Weston,请输入此命令
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston --tty="$WESTON_TTY" --idle-time=0 &
• 可选:将环境变量 WAYLAND_DEBUG 设置为 server 以将协议消息从服务器转储到 stderr
$ export WAYLAND_DEBUG=server
• 可选:使用 --use-egldevice 开关禁用 GBM 交换链,并使用 EGLStream 写入 Weston 输出。
2. 要使用 weston-launch 以非 root 用户身份启动 Weston,请输入以下命令
$ sudo groupadd weston-launch
$ sudo usermod -a -G weston-launch $USER
$ sudo chown root /usr/bin/weston-launch
$ sudo chmod +s /usr/bin/weston-launch
$ weston-launch &
7. 运行 Wayland 客户端
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-simple-egl
• 可选:将环境变量 WAYLAND_DEBUG 设置为 1 以将所有协议消息转储到 stderr
$ WAYLAND_DEBUG=1
8. 要运行 Weston 测试,您必须使用命令行选项或 weston.ini 中的设置加载模块 weston-test.so。例如,您可以指定选项:--modules=/usr/lib/aarch64-linux-gnu/tegra/weston/weston test.so。
9. 要在设备上使用 ivi-shell 和 ivi-controller 启动 Weston,请将参数传递给 weston 二进制文件,如下所示:--shell=ivi-shell.so --modules=ivi-controller.so。
多显示头
Weston 在所有 Jetson 设备上都支持具有多个覆盖层的多显示头。使用 weston.ini 设置监视器的预期分辨率和方向。
如果连接了多个显示器,则应用程序会在启动时鼠标指针所在的显示器上启动。应用程序启动后,您可以将其拖过显示器之间的边界。
如果连接了多个显示器并且它们具有不同的分辨率,则 Weston 会报告窗口显示超过 50% 的显示器的帧速率。如果在 Weston 运行时移除监视器(热移除),则正在运行的应用程序会动态转移到剩余的活动监视器。
weston.ini 显示选项示例
使用此示例作为在 weston.ini 中设置您自己的显示选项的模型。
name=HDMI-A-1
mode=1920 x 1080
transform=90 (0,90,180,270)
热插拔
Weston 使用 udev 监视直接渲染管理器 (DRM) 子系统发送的事件。当显示配置更改时,udev 接收 HOTPLUG 事件。它调用 drmModeGetResources() 来识别已添加或移除的连接器,并采取相应的操作。
在 T210 上,没有真正的内核模式 DRM 驱动程序;相反,有一个用户模式 DRM 驱动程序 drm-nvdc 和一个虚拟内核模式 DRM 驱动程序 tegra-udrm。这些驱动程序协同工作,为 Weston 提供类似真实 DRM 驱动程序的接口。tegra-udrm 驱动程序在显示连接状态更改时发出 HOTPLUG 事件信号。
已验证的用例
• 在启动 Weston 后,断开并连接 HDMI™ 显示器。
• 在应用程序 nvgldemo 运行时,断开并连接 HDMI 显示器,并验证连接后应用程序绘图是否可见。
• 在未连接 HDMI 显示器的情况下启动 Weston,然后连接 HDMI 显示器。
• 在未连接 HDMI 显示器的情况下启动 Weston,启动 nvgldemo 应用程序,然后连接 HDMI 显示器。
上述所有用例也已通过 DisplayPort 显示器验证。
Weston 中修复的问题
• 重新连接显示器时,应用程序窗口消失。
• 在未连接显示器时,使用 ivi-shell 会导致 Weston 崩溃。
• 在 ivi-shell 中添加了对多个热插拔显示器的支持。
ivi-shell 最初并非设计为支持热插拔。这是 NVIDIA 的增强功能。
该修复程序向 ivi-vm 添加了一个协议,使客户端可以接收由 ivi-controller 发送的热插拔事件。客户端必须在使用 ivi-layermanagement API 的热插拔期间处理事件,以重新定位表面、销毁表面等等。客户端可以创建侦听器来侦听 ivi-wm-screen 接口中的 connector_name、screen_id 和 screen_destroy 事件,以获取 ivi-wm 协议以获取热插拔通知。
以下是一些示例代码
static void
screen_id(void *data, struct ivi_wm_screen *ivi_wm_screen, uint32_t id);
static void
screen_destroy(void *data,struct ivi_wm_screen *ivi_wm_screen, uint32_t id);
static void
connector_name(void *data, struct ivi_wm_screen *ivi_wm_screen, const char *process_name);
struct ivi_wm_screen_listener wm_screen_listener = {
screen_id,
screen_destroy,
layer_added,
connector_name,
error,
};
ivi_wm_screen_add_listener(ivi_wm_screen, &wm_screen_listener, args);
已知问题
• DRM 模块目前无法通知 Weston 页面翻转失败。因此,当 Weston 配置为支持多个显示器时,在特定时间热插拔显示器可能会导致 drmAtomicCommit() 因“页面翻转挂起”断言而失败。
Weston 中的合成模式
Jetson 设备每个显示头有多个平面。平面的主要类型有
• 主平面
• 覆盖平面
• 光标平面
在每一帧,Weston 都会评估所有表面和视图,并选择以下策略之一来合成它们
• 仅覆盖模式:Weston 尝试为每个表面或视图分配一个平面。如果不可能,它将切换到“混合模式”。
• 混合模式:Weston 尝试为某些表面和视图分配覆盖平面,使用 GL 合成剩余的表面和视图,并将结果更新到主平面。如果仍然不可能,它将继续使用“仅 GL 模式”。
• 仅 GL 模式:Weston 使用 GL 合成所有表面和视图,并将结果更新到主平面。
使用所有这些策略,Weston 确保保留表面和视图的渲染顺序。您可以通过将环境变量 WESTON_FORCE_RENDERER 设置为 1 来强制使用仅 GL 模式合成。
演示应用程序 weston-simple-dmabuf-egldevice 演示了 Weston 中的混合模式合成,其中一些表面被分配了覆盖平面,而另一些表面则使用 GL 合成到主平面。
您可以使用应用程序 weston-debug 来验证是否正在分配覆盖平面。使用以下步骤
1. 如果 X 正在运行,请停止 X 并准备设备以启动 Weston
$ sudo service gdm stop; sudo pkill -9 Xorg
$ unset DISPLAY
$ mkdir /tmp/xdg
$ chmod 700 /tmp/xdg
$ export WESTON_TTY=1
$ sudo modprobe tegra-udrm modeset=1
$ sudo ln -sf /usr/lib/aarch64-linux-gnu/tegra/libnvgbm.so /usr/lib/aarch64-linux-gnu/libgbm.so.1
2. 使用 --debug 开关启动 Weston
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston --tty="$WESTON_TTY" --idle-time=0 --debug &
3. 启动几个 Weston 客户端应用程序
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-simple-egl &
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-simple-dmabuf-egldevice &
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-simple-dmabuf-egldevice &
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-simple-dmabuf-egldevice &
4. 运行 weston-debug 应用程序
$ sudo XDG_RUNTIME_DIR=/tmp/xdg ./weston-debug -a
5. 在 weston-debug 输出中查找如下所示的信息。蓝色表面是覆盖合成的,绿色表面是 GL 合成的。
Layer 5 (pos 0x50000000)
View 0 (role xdg_toplevel, PID 8080, surface ID 3, top-level window 'simple-dmabuf-egldevice', 0x33c798b0)
position: (714, 860) -> (970, 1116)
[not opaque]
outputs: 0 (HDMI-A-1) (primary)
dmabuf buffer
format: 0x34325258 XRGB8888
modifier: 0x3800000000fe014
View 1 (role xdg_toplevel, PID 8073, surface ID 3, top-level window 'simple-dmabuf-egldevice', 0x33bb9500)
position: (209, 591) -> (465, 847)
[not opaque]
outputs: 0 (HDMI-A-1) (primary)
dmabuf buffer
format: 0x34325258 XRGB8888
modifier: 0x3800000000fe014
View 2 (role xdg_toplevel, PID 8066, surface ID 3, top-level window 'simple-dmabuf-egldevice', 0x31769110)
position: (1129, 339) -> (1385, 595)
[not opaque]
outputs: 0 (HDMI-A-1) (primary)
dmabuf buffer
format: 0x34325258 XRGB8888
modifier: 0x3800000000fe014
View 3 (role xdg_toplevel, PID 8051, surface ID 9, top-level window 'simple-egl', 0x314c6430)
position: (1343, 642) -> (1593, 892)
[not opaque]
outputs: 0 (HDMI-A-1) (primary)
EGL buffer
Layer 6 (pos 0x2)
...
[view] evaluating view 0x33c798b0 for output HDMI-A-1 (0)
[view] view 0x33c798b0 format: XRGB8888
[overlay] provisionally placing view 0x33c798b0 on overlay 4002 in mixed mode
[view] evaluating view 0x33bb9500 for output HDMI-A-1 (0)
[view] view 0x33bb9500 format: XRGB8888
[overlay] provisionally placing view 0x33bb9500 on overlay 4001 in mixed mode
[view] evaluating view 0x31769110 for output HDMI-A-1 (0)
[view] view 0x31769110 format: XRGB8888
[overlay] not placing view 0x31769110 on overlay: no free overlay planes
[view] evaluating view 0x314c6430 for output HDMI-A-1 (0)
[overlay] not placing view 0x314c6430 on overlay: couldn't get fb
[repaint] Using mixed state composition
[repaint] view 0x33c798b0 on Overlay plane 4002
[repaint] view 0x33bb9500 on Overlay plane 4001
[repaint] view 0x31769110 using renderer composition
[repaint] view 0x314c6430 using renderer composition
Weston 中的 NV16/NV24
Weston GL 合成器通过共享内存缓冲区添加了对 NV16 和 NV24 内容的支持。
使用 WL_SHM_FORMAT_NV24 枚举的应用程序可以替换 DRM_FORMAT_NV24,因为按照惯例,这两个枚举都使用 drm_fourcc.h 中定义的符号。
共享内存渲染
Weston 测试 color-format.weston 对 Weston 当前支持的所有格式执行共享内存渲染。虽然作为测试用例实现,但它旨在用于视觉验证,并且必须手动终止。
要运行测试用例
1. 使用 weston-test.so 模块启动 Weston,例如
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston --tty="$WESTON_TTY" --idle-time=0 --modules=weston-test.so &
2. 输入此命令以执行测试应用程序
$ sudo XDG_RUNTIME_DIR=/tmp/xdg color-format.weston
该应用程序显示八种颜色测试模式,每种模式都使用不同的颜色格式渲染。所有模式都应基本相同,只有因格式限制而造成的细微差异。
3. 要终止测试,请输入 Ctrl-C。
DMA 缓冲区渲染
DRM 现在支持 NV16 和 NV24 颜色格式。要使用这些格式,请通过公开的 EXT_image_dma_buf_import 和 EXT_image_dma_buf_import_modifiers 扩展从 DMA 缓冲区构造 EGLImage。
当前仅支持块线性 DMA 缓冲区布局。DRM_FORMAT_NV21、DRM_FORMAT_NV16 和 DRM_FORMAT_NV24 已添加到 supported_drm_formats。
要运行已验证的用例(视频播放测试)
• 输入此命令
$ gst-launch-1.0 filesrc location=<mp4_src_file> ! qtdemux ! h264parse ! nvv4l2decoder ! nvvidconv ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)<format>' ! nvdrmvideosink
其中
• <mp4_src_file> 是 apt 源文件的路径名
• <format> 是 NV16 或 NV24
gst-launch-1.0 命令是用于显示视频的 GStreamer 管道。它使用 nvvidconv 插件将流中的其他格式转换为 NV16/NV24。视频通过 nvdrmvideosink 插件显示,该插件在内部使用 DRM。
VPR 内存
您可以使用
nbuf_utils、
通用缓冲区管理 (GBM) 和
EGLStream 分配 VPR 内存。
• 使用 nvbuf_utils:将 NvBufferTag_PROTECTED 标记添加到 struct NvBufferCreateParams 的 NvBufferTag 成员,并将其传递给 NvBufferCreate()。
• 使用 GBM:为 gbm_bo_create() 指定 GBM_BO_USE_PROTECTED 用法标志。
• 使用 EGLStream:在创建 eglSurface 对象时添加 EGL_PROTECTED_CONTENT_EXT 属性。为受保护的纹理指定纹理参数 GL_TEXTURE_PROTECTED_EXT。
要使用 GL 写入受保护的纹理,您还必须使用受保护的上下文,您可以通过指定 EGL_PROTECTED_CONTENT_EXT 属性来创建该上下文。请注意,当您将 dmabuf 导入 EGL 时,如果 dmabuf 是在 VPR 内存中创建的,则还必须指定此属性。
要运行示例用例
• 使用 -p 开关运行 weston-simple-dmabuf-egldevice 应用程序。
要验证结果的正确性,请在屏幕上检查它。它应该与您在不使用 VPR 内存的情况下运行应用程序时相同。
当前限制
VPR 内容只能通过覆盖 GL 合成在屏幕上渲染。GL 尚不支持受保护的内容。此类支持将在以后的版本中添加。
因此,如果屏幕上有多个窗口超过覆盖合成的限制,则不会为超出限制的窗口渲染受保护的内容。
HDCP 支持尚不可用。它将在未来的版本中支持。但是,对于 Jetson Nano 设备,即使不建立 HDCP 链接,您也可以在屏幕上显示 VPR 内容。
Weston dma-buf 支持
客户端可以使用 Wayland 的 Linux DMA-BUF 不稳定 V1 协议将 dma-buf 缓冲区发布到 Weston。具有 Weston 的 Dma-buf 支持具有以下组件。
缓冲区分配
GBM 通常用于分配缓冲区,这些缓冲区由 dma-buf 文件描述符支持。
此代码段显示了如何使用 GBM 分配缓冲区
drm_fd = open("/dev/dri/card0", O_RDWR);
device = gbm_create_device(drm_fd);
bo = gbm_bo_create_with_modifiers(device, width, height,
format, modifiers, modifiers_count);
Weston 支持格式 DRM_FORMAT_XRGB8888 和 DRM_FORMAT_ARGB8888。
modifier 是特定于供应商的缓冲区布局参数的编码。Weston 支持的修饰符受 DRM 支持(读取 IN_FORMATS 平面属性 blob)和 EGL 支持(调用 eglQueryDmaBufModifiersEXT() )。
从 CPU 写入/读取缓冲区
您可以使用此 API 函数将数据直接写入 GBM 缓冲区
gbm_bo_write(bo, user_buffer, sizeof user_buffer);
您还可以内存映射 GBM 缓冲区并获取 CPU 可访问的地址,以用于写入或读取其中的数据。以下代码段显示了如何操作
uint32_t dst_stride = 0;
void *gbo_mapping = NULL;
// 将 bo 映射到 CPU 可访问的地址。
char *dst_ptr = gbm_bo_map(bo,
0, 0,
width,
height,
GBM_BO_TRANSFER_READ_WRITE,
&dst_stride,
&gbo_mapping);
// 将数据写入 dst_ptr 或从中读取数据。
. . .
// 取消映射 bo。
gbm_bo_unmap(bo, gbo_mapping);
将 dma-buf 缓冲区发布到 Weston 的 Wayland 协议
Weston 使用通用缓冲区管理 (GBM) 库来分配缓冲区,这些缓冲区由 dma-buf 文件描述符支持。客户端应用程序必须调用以下 GBM 函数才能从 GBM 缓冲区对象获取 dma-buf 文件描述符和关联的参数。要将 dma-buf 发布到 Wayland 表面,必须通过 Linux DMA-BUF 不稳定 V1 协议提供文件描述符和参数。
以下代码段显示了涉及的主要调用。
stride = gbm_bo_get_stride_for_plane(bo, 0);
offset = gbm_bo_get_offset(bo, 0);
handle = gbm_bo_get_handle_for_plane(bo, 0);
modifier = gbm_bo_get_modifier(bo);
drmPrimeHandleToFD(drm_fd, handle, 0, &dmabuf_fd);
zwp_linux_buffer_params_v1_add(params, dmabuf_fds, 0, offset,
stride, modifier >> 32,
modifier & 0xffffffff);
zwp_linux_buffer_params_v1_create(params, width, height,
format, flags);
Weston 中的 GL 渲染器
Weston 中的 GL 渲染器使用 EGL_EXT_image_dma_buf_import 和 EGL_EXT_image_dma_buf_import_modifiers 扩展,从它通过 Linux DMA-BUF 不稳定 V1 协议接收的 dma-buf 对象创建 EGLImage。Weston 通过调用 eglQueryDmaBufModifiersEXT() 获取要与此 EGLImage 一起使用的 GL 纹理目标,并将 EGLImage 绑定到纹理。
Weston 中的显示硬件合成
Weston 中的 DRM 合成器调用 drmModeAddFB2WithModifiers(),以将 DRM 帧缓冲区 ID 与通过 Linux DMA-BUF 不稳定 V1 协议接收的 dma-buf 相关联。然后,它使用帧缓冲区 ID 将 dma-buf 呈现给可用的显示硬件平面之一,在旧版路径中使用 drmModeSetPlane(),或在原子模式设置路径中使用 drmModeAtomicCommit()。这采用翻转的形式,其中对新缓冲区的引用在垂直消隐期间交换。
Weston dma-buf 示例
weston-dmabuf-formats 是一个简单的应用程序,用于测试 Weston dmabuf 对不同格式(如 XRGB8888、NV12、NV16、NV24)的支持。
输入此命令以启动应用程序
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston-dmabuf-formats --import-format=<format> --loop=<count> --use-gbm
其中
• <format> 是 NV16 或 NV24。
• <count> 是要执行的迭代次数。
• --use-gbm 表示应用程序将使用 GBM 而不是 nvbuf_utils 进行缓冲区分配。
weston-debug
客户端应用程序 weston-debug 使用 weston-debug 协议接收和打印调试消息。例如,当 Weston 重新合成时,它会打印所有表面视图以及有关将其分配给覆盖层和 GL 合成的决策过程的描述。
要使 weston-debug 工作,您必须使用 ‑‑debug 开关运行 Weston。请勿在生产环境中使用此开关。
您可以传递 weston-debug 附加参数来选择要显示的调试输出类别
$ sudo XDG_RUNTIME_DIR=/tmp/xdg weston –debug
$ sudo XDG_RUNTIME_DIR=/tmp/xdg ./weston-debug -a
或者,您可以通过设置环境变量 WAYLAND_DEBUG=server 来启用 Weston 调试输出,并通过设置 WAYLAND_DEBUG=1 来启用 Weston 客户端调试。
Gnome-Wayland 桌面 Shell 支持
在 L4T 版本 32.4.2 中,NVIDIA 支持 Gnome-Wayland 窗口系统。L4T 对 Gnome-Wayland 的支持目前处于实验阶段。
本节介绍一些使用 Gnome-Wayland 的步骤。
要启动窗口系统
1. 在 /etc/systemd/nvuser.sh 中,更改
GNOME_WAYLAND="0"
为
GNOME_WAYLAND="1"
2. 在 /etc/modprobe.d/tegra-udrm.conf 中,取消注释行
#options tegra-udrm modeset=1
(删除行首的“#”。)
3. 在 /etc/systemd/nv.sh 中,更改
DISABLE_MESA_EGL="1"
为
DISABLE_MESA_EGL="0"
4. 在 /etc/systemd/system/nvargus-daemon.service 中,通过在行首插入“;”来阻止 nvargus 守护程序在启动时启动
ExecStart=/usr/sbin/nvargus-daemon
5. 重启设备。如果启用 auto-login,L4T 会将您登录到 Wayland 会话;否则,它会显示可用接口列表(例如 Wayland、命令行),并将您登录到您选择的类型的会话。