需要在 Linux 帧缓冲区中绘制光标

Posted

技术标签:

【中文标题】需要在 Linux 帧缓冲区中绘制光标【英文标题】:Need to draw cursor in Linux framebuffer 【发布时间】:2016-06-22 15:02:35 【问题描述】:

我需要在没有X11的Linux下在屏幕上画一个光标(鼠标指针)。这适用于嵌入式系统,其中所有其他绘图都直接发生在帧缓冲区中 (/dev/fb0)。

    我目前正在查看的 GUI 库不提供任何光标支持。 我可以自己执行 blitting,但我担心外观和性能,部分原因是我似乎无法与 vsync 同步 (FBIO_WAITFORVSYNC)。 我知道几乎所有的图形芯片都支持硬件光标,但 DirectFB 已死,libdrm 需要 X11,Mesa 也是如此。

在What is hardware cursor and how does it work? 中,OP 声称通过ioctl 调用实现了这一目标,并表示这很简单,但拒绝提供更多细节,因为他的代码是专有的。我知道 FBIO_CURSOR,但它似乎是非标准的,并且总是在我的 3.10.0 内核上返回 EINVAL

在没有 X11 的情况下绘制帧缓冲区光标的正确方法是什么?

【问题讨论】:

乔希,你发现了吗?今晚我自己也遇到了这个问题。在 FBIO_CURSOR 方面没有多少。 @Stéphane 请看我刚刚发布的答案。 【参考方案1】:

我最终推出了自己的光标支持,因为内核支持似乎取决于特定视频驱动程序支持的任何内容。表演结束了我的目的。这是我所做的:

打开/dev/fb0帧缓冲区,根据需要调整vinfo,mmap帧缓冲区,malloc两个缓冲区大小与帧缓冲区相同。其中一个缓冲区是我的后台缓冲区,所有绘图都发生在这里。另一个是我绘制光标的“光标”缓冲区。 打开相应的 /dev/input/eventX 以准备读取鼠标事件。 定义一个“刷新”函数,以便在将某些内容绘制到后台缓冲区或有鼠标活动时调用。 poll 用于具有合理超时的鼠标事件。我使用了 500 毫秒的超时并将其放在 pthread 中,这样它的性能开销就很小。 “刷新”函数memcpy'将后台缓冲区放入游标缓冲区,并将游标绘制在上面。 (根据图像here,我擦除光标下的掩码位并绘制光标位。)然后将光标缓冲区memcpy'ed 到帧缓冲区中。 (我用两个互斥锁保护刷新功能以获得更好的性能。我在将后台缓冲区复制到游标缓冲区之前获取第一个并在绘制游标后释放它。我在绘制游标之前获取第二个并在之后释放它将光标缓冲区复制到帧缓冲区。在进行大量非常快速的绘图时,这会显着提高性能。)

我做出一些决定的几个原因:

写入帧缓冲区相当快,但读取帧缓冲区要慢得多,因此使用常规的malloc'ed 内存作为后台和光标缓冲区。 memcpy 比我能写的任何东西都快得多,而且是线程安全的。 对帧缓冲区的并发访问速度很慢,可能是因为memcpy 在尝试访问当前正在使用的区域时锁定了区域和块。这就是为什么我使用两个互斥锁来保护从后台缓冲区到游标缓冲区以及从游标缓冲区到帧缓冲区的副本。 poll0 超时等效于使用大量 CPU 周期的紧密循环,因此使用非零超时。但是poll 会在输入有活动时立即返回,因此响应速度非常好。

在我的硬件上,我没有找到与垂直消隐同步的可用方法(一些ioctl 显然是无操作的),但上述方法没有表现出特别的撕裂。是的,这种方法使用 两个 屏幕外缓冲区,在我的 1920 x 1080 16 位/像素屏幕上,每个缓冲区都需要 4 MB,但它非常简单,足以满足我的需求。

【讨论】:

以上是关于需要在 Linux 帧缓冲区中绘制光标的主要内容,如果未能解决你的问题,请参考以下文章

Linux 帧缓冲查看器

在 OpenGL 中显示帧缓冲区

将如何绘制到 ds 的子显示,就好像它是一个帧缓冲区一样?

使用 linux 帧缓冲区进行图形但禁用控制台文本

OpenGL ES 2 控制台帧缓冲光标

在OpenGL中绘制到半透明帧缓冲区时如何抗锯齿? [复制]