在fb_var_screeninfo中设置yres_virtual时出现无效参数错误

时间:2013-02-25 16:26:40

标签: c linux framebuffer doublebuffered

我正在尝试创建一个直接写入framebuffer / dev / fb0的linux应用程序。为了使其成为双缓冲,我尝试使虚拟屏幕的大小是屏幕的两倍。这是我写的程序:

struct fb_var_screeninfo screeninfo_var;
struct fb_fix_screeninfo screeninfo_fixed;
unsigned int* screenbuffer;

void gfx_init()
{
    fb0 = open("/dev/fb0", O_RDWR);
    if(fb0 == 0)
        error("Could not open framebuffer located in /dev/fb0!");

    if (ioctl(fb0, FBIOGET_FSCREENINFO, &screeninfo_fixed) == -1)
        error("Could not retrive fixed screen info!");

    if (ioctl(fb0, FBIOGET_VSCREENINFO, &screeninfo_var) == -1)
        error("Could not retrive variable screen info!");

    screeninfo_var.xres_virtual = screeninfo_var.xres;
    screeninfo_var.yres_virtual = screeninfo_var.yres * 2;
    screeninfo_var.width = screeninfo_var.xres;
    screeninfo_var.height = screeninfo_var.yres;
    screeninfo_var.xoffset = 0;
    screeninfo_var.yoffset = 0;

    if (ioctl(fb0, FBIOPUT_VSCREENINFO, &screeninfo_var) == -1)
        error("Could not set variable screen info!");

    info("Detected monitor of %ix%i pixels using %i bit colors.",screeninfo_var.xres, screeninfo_var.yres, screeninfo_var.bits_per_pixel);

    screenbuffersize = screeninfo_var.xres_virtual * screeninfo_var.yres_virtual * screeninfo_var.bits_per_pixel/8;
    screenbuffer = (unsigned int *)mmap(0, screenbuffersize, PROT_READ | PROT_WRITE, MAP_SHARED, fb0, 0);
    if( (long)screenbuffer == 0 || (long)screenbuffer == -1 )
        error("Failed to map framebuffer to device memory!");
}

程序在ioctl(fb0, FBIOPUT_VSCREENINFO, &screeninfo_var)报告错误无效参数时失效。删除行screeninfo_var.yres_virtual = screeninfo_var.yres * 2;时它运行正常(但没有双缓冲)。

有人看到我在这里做错了吗?

2 个答案:

答案 0 :(得分:0)

这是一个常见问题,它是由视频驱动程序的限制引起的。例如,英特尔的810芯片组仅允许640x480分辨率,而Broadcom将宽度限制为不超过1200(http://www.raspberrypi.org/phpBB3/viewtopic.php?f=66&t=29968)。

除非您更改驱动程序或显卡本身(如果可能),否则您无法在此处执行此操作。

编辑:如果您使用的是PC,请尝试使用vesafb,而不是英特尔的驱动程序。

这里有一个提示:http://www.mail-archive.com/debian-russian@lists.debian.org/msg27725.html

答案 1 :(得分:0)

为了在将来让人头疼,有一种方法可以在linux上使用低级图形(例如/ dev / fb0)正确地加倍缓冲。但是根据这个帖子:https://forum.odroid.com/viewtopic.php?f=55&t=8741通过创建一个原始大小加倍的虚拟帧缓冲区来实现双缓冲帧缓冲区是不可能的(我已经读过,树莓PI可能是这条规则的一个例外,因为它由不同的驱动程序支持。)

在linux上使用低级图形加倍缓冲的正确方法是通过libdrm(或/ dev / dri / card0)。我在这里有一个非常好的例子:https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c。将/ dev / fb0代码转换为/ dev / dri / card0代码并不是很难。

无论如何,我希望我能帮助那些可能在将来遇到这个问题的人。