有没有办法强制linux帧缓冲区立即显示帧? 我正在用C++制作视频播放器,它在Linux框架缓冲区上显示视频。帧在更新后不直接可见,但仅在tty更新后可见(例如,光标闪烁或我按下一个键)

有没有办法强制linux帧缓冲区立即显示帧? 我正在用C++制作视频播放器,它在Linux框架缓冲区上显示视频。帧在更新后不直接可见,但仅在tty更新后可见(例如,光标闪烁或我按下一个键),c++,linux,graphics,intel,framebuffer,C++,Linux,Graphics,Intel,Framebuffer,我不认为cpu会变慢/做太多的事情,因为没有一个内核有100%的使用率,程序最多使用30%的cpu 如果我运行htop(它将光标隐藏在tty上),则帧缓冲区将仅在htop刷新时更新(每1.5秒一次) 我正在笔记本电脑(acer Swift 3)上使用arch linux和linux 5.11.11-arch1-1(现在是5.11.14-arch1-1),该笔记本电脑具有双核Intel Core i3-8145U和集成图形(Intel UHD graphics 620)以及i915驱动程序 有没有

我不认为cpu会变慢/做太多的事情,因为没有一个内核有100%的使用率,程序最多使用30%的cpu

如果我运行htop(它将光标隐藏在tty上),则帧缓冲区将仅在htop刷新时更新(每1.5秒一次)

我正在笔记本电脑(acer Swift 3)上使用arch linux和linux 5.11.11-arch1-1(现在是5.11.14-arch1-1),该笔记本电脑具有双核Intel Core i3-8145U和集成图形(Intel UHD graphics 620)以及i915驱动程序

有没有办法告诉帧缓冲区更新? 我尝试使用fsync,但它没有任何作用

在tty上打印换行符会使tty更新,但似乎没有必要。 我尝试了
ioctl(tty1_fd,KDSETMODE,KD_GRAPHICS)
,但这将冻结输出,我必须通过ssh登录并运行
ioctl(tty1_fd,KDSETMODE,KD_TEXT)
对笔记本电脑执行任何操作或查看更新的帧缓冲区

这只会影响我的笔记本电脑。如果我在带有双核AMD E-350和(集成?)高级微设备[AMD/ATI]Gletcher[Radeon HD 6310]图形和linux 5.11.10-gentoo-x86_64的PC上运行它,一切都会正常工作

他也有同样的问题

我试着用mplayer播放视频,但也不起作用。 如果我转到tty3并使用
mplayer-vo fbdev2:/dev/fb0 video.mp4运行它,视频将正常播放,没有任何延迟。
如果我切换到tty4,视频(而不是声音)将开始口吃。
它看起来像是仅在tty更新帧缓冲区后才显示帧缓冲区的内容(即光标闪烁或写入新字符)
它在tty3上工作,因为mplayer在每次屏幕更新后写入当前时间,这将使帧缓冲区更新

最简单的例子:

#包括
#包括
#包括
#包括
#包括
#包括
constexpr size\u t WIDTH=1920;//帧缓冲区宽度(以像素为单位)
constexpr size\u t HEIGHT=1080;//帧缓冲区高度(以像素为单位)
constexpr size\u t字节/u像素=4;//每像素字节数(bgra)
constexpr size\u t MEM\u WIDTH=宽度*每像素字节数;//内存中的帧缓冲区宽度
constexpr size\u t FRAME\u size=MEM\u WIDTH*HEIGHT;//一帧的大小
constexpr size\u t FPS=24;//帧速率
静态constexpr size\u t NSPF=FPS?std::nano::den/(FPS*std::nano::num):0;//每帧纳秒
静态constexpr std::chrono::纳秒睡眠时间{NSPF};
int fb_fd;//帧缓冲区文件描述符
uint8_t*fb_mem;//指向mmaped帧缓冲区的指针
静态空集像素(大小x、大小y、黑色)
{
自动*像素=&fb_mem[mem_宽度*y+x*字节/u像素];
标准:填充(像素,4,黑色?0:255);
}
int main()
{
fb_fd=打开(“/dev/fb0”,O_RDWR);
fb_mem=静态强制转换(mmap(nullptr,帧大小,保护读取,保护写入,映射共享,fb_fd,0));
尺寸x=0;
尺寸y=100;
布尔黑=假;
while(true)
{
用于(大小x=x;x<\ux+10;x++)
设置像素(x、y、黑色);
如果(x>=宽度)
{
x%=WIDTH;//返回到行的起始端
黑色=!黑色;
}
std::this_thread::sleep_for(sleep_DURATION);//等待下一帧
}
}

请说明使用
volatile
(或在没有优化的情况下编译,或使用编译器围栏/内存屏障,如
asm(“:”内存”)
)有帮助吗?我想知道编译器是否以某种方式重新排序了您的存储,因为您告诉它只使用普通指针类型(
uint8\t*
),这意味着它可以假设内存内容在优化方面不是一个明显的副作用。嗯,如果它与不同的硬件不同,可能不会,除非你在另一个系统上也使用了不同的编译器版本/选项。我通常使用
clang++-march=native-flto-Ofast
编译它。我试着只使用
clang++
clang++-O0
g++
g++-O0
,使指针
volatile uint8*
并在所有地方添加
asm(“::“内存”)
。我尝试编译32位(使用
-m32
),但它也没有做任何事情。我认为这是一种省电功能,使帧缓冲区仅在必要时更新,因为当闪烁的光标打开/关闭并按住任何键或在每行更新帧缓冲区后打印换行符时,它会更新。
-O0
足以排除这种情况下的任何存储优化(这有点类似于使所有内容都变得不稳定
),即使进行了优化,对的
sleep\u的调用也不会发生这种情况。但值得一试,并留在
asm(“:”内存“)中
在存储帧缓冲区之后(例如,在睡眠之前)对于长期健壮性/代码质量来说是个好主意。