有任何方法可以迫使Linux Framebuffer立即显示框架? 我在C ++中制作视频播放器,该视频播放器在Linux Framebuffer上显示视频。更新后直接可见框架,但仅在更新TTY之后(例如光标闪烁或...

问题描述 投票:0回答:0
有什么方法可以告诉FrameBuffer更新? 我尝试使用fsync,但没有做任何事情。

在TTY上打印新线会进行TTY更新,但这似乎是不必要的。 我尝试了

ioctl(tty1_fd, KDSETMODE, KD_GRAPHICS)

,但这会冻结输出,我必须通过SSH登录并运行

ioctl(tty1_fd, KDSETMODE, KD_TEXT)

以使用笔记本电脑进行任何操作或查看更新的Framebuffer。

这只会影响我的笔记本电脑。如果我在具有双核AMD E-350和(集成?)高级微设备[AMD/ATI]摔跤手[Radeon HD 6310]图形和Linux 5.11.10-Gentoo-X86_644的PC上运行它,一切正常。

这个framebuffer示例

有相同的问题。

我尝试与mplayer一起播放视频,但也行不通。 如果我去TTY3并与

mplayer -vo fbdev2:/dev/fb0 video.mp4

一起运行。
如果我切换到TTY4,则视频(不是声音)将开始口吃。
它看起来只有在TTY更新FrameBuffer之后显示帧缓冲程序的内容(即光标眨眼或写了新字符)
它在TTY3上起作用,因为Mplayer会在每个屏幕更新后写入当前时间,这将使FrameBuffer更新。
小型示例:
#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
    }
}

您可能需要更多的IOCTL,建议的方法是动态获取数据。 我不确定C ++,但这是我用于此类任务的C片段:

struct fb_fix_screeninfo fix = {0}; struct fb_var_screeninfo var = {0}; // get fb fixed & variable info ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix); ioctl(fb_fd, FBIOGET_VSCREENINFO, &var); // draw a pixel set_pixel(0, 0, false); // send fb update in one of two ways: // FBIOPAN_DISPLAY tries to update using panning method, // if you don't change var.yoffset it should keep it's // position. // Modifying var.activate should work if panning fails. // PS: var.yoffset can be used for double buffering // if var.yres_virtual >= var.yres *2; but you must take // that offset into account in the set_pixel() code. if (ioctl(fb_fd, FBIOPAN_DISPLAY, &var) != 0){ // panning failed so you can refresh now using this var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; // or (non-blocking) make the update wait for vblank // (not supported by all drivers) //var.activate = FB_ACTIVATE_VBL; // send the modified var data ioctl(fb_fd, FBIOPUT_VSCREENINFO, &var); }

c++ linux graphics intel framebuffer
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.