如何解决有没有办法强制linux framebuffer立即显示帧?
我正在用 C++ 制作一个视频播放器,它在 linux 帧缓冲区上显示视频。帧在更新后不直接可见,但只有在 tty 更新后才可见(例如,光标闪烁或我按住某个键)。
我不认为 cpu 会变慢/做太多事情,因为没有一个内核有 100% 的使用率,而程序最多使用 30% 的 cpu。
如果我运行 htop,它将光标隐藏在 tty 上,帧缓冲区只会在 htop 刷新时更新(每 1.5 秒)。
我在带有双核 Intel Core i3-8145U 和集成显卡(Intel UHD Graphics 620) 带有 i915 驱动程序。
有没有办法告诉帧缓冲区更新? 我尝试使用 fsync,但它没有做任何事情。
在 tty 上打印换行符会使 tty 更新,但这似乎没有必要。
我尝试了 ioctl(tty1_fd,KDSETMODE,KD_GRAPHICS)
,但这会冻结输出,我必须通过 ssh 登录并运行 ioctl(tty1_fd,KD_TEXT)
才能对笔记本电脑执行任何操作或查看更新的帧缓冲区。
这只会影响我的笔记本电脑。如果我在配备双核 AMD E-350 和(集成?)Advanced Micro Devices [AMD/ATI] Wrestler [Radeon HD 6310] 显卡和 linux 5.11.10-gentoo-x86_64 的 PC 上运行它,一切正常。
This framebuffer example 也有同样的问题。
我尝试用 mplayer 播放视频,但它也不起作用。
如果我转到 tty3 并使用 mplayer -vo fbdev2:/dev/fb0 video.mp4
运行它,视频将正常播放而没有任何延迟。
如果我切换到 tty4,视频(不是声音)会开始卡顿。
看起来它仅在 tty 更新帧缓冲区后才显示帧缓冲区的内容(即光标闪烁或写入新字符)
它适用于 tty3,因为 mplayer 在每次屏幕更新后写入当前时间,这将使帧缓冲区更新。
最小示例:
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <chrono>
#include <thread>
#include <sys/mman.h>
constexpr size_t WIDTH = 1920; // framebuffer width (in pixels)
constexpr size_t HEIGHT = 1080; // framebuffer height (in pixel)
constexpr size_t BYTES_PER_PIXEL = 4; // bytes per pixel (bgra)
constexpr size_t MEM_WIDTH = WIDTH * BYTES_PER_PIXEL; // framebuffer width in memory
constexpr size_t FRAME_SIZE = MEM_WIDTH * HEIGHT; // size of one frame
constexpr size_t FPS = 24; // framerate
static constexpr size_t NSPF = FPS ? std::nano::den / (FPS * std::nano::num) : 0; // nanoseconds per frame
static constexpr std::chrono::nanoseconds SLEEP_DURATION{NSPF};
int fb_fd; // framebuffer filedescriptor
uint8_t *fb_mem; // pointer to mmaped framebuffer
static void set_pixel(size_t x,size_t y,bool black)
{
auto *pixel = &fb_mem[MEM_WIDTH * y + x * BYTES_PER_PIXEL];
std::fill_n(pixel,4,black ? 0 : 255);
}
int main()
{
fb_fd = open("/dev/fb0",O_RDWR);
fb_mem = static_cast<uint8_t *>(mmap(nullptr,FRAME_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fb_fd,0));
size_t x = 0;
size_t y = 100;
bool black = false;
while (true)
{
for (size_t _x = x; x < _x + 10; x++)
set_pixel(x,y,black);
if (x >= WIDTH)
{
x %= WIDTH; // go back to the beginning side of the line
black = !black;
}
std::this_thread::sleep_for(SLEEP_DURATION); // wait for the next frame
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。