【问题标题】:invalid argument error when setting yres_virtual in fb_var_screeninfo在 fb_var_screeninfo 中设置 yres_virtual 时出现无效参数错误
【发布时间】:2013-02-25 16:26:40
【问题描述】:

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

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; 时,它运行良好(但没有双缓冲)。

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

【问题讨论】:

  • 你有想过这个吗?我目前遇到了类似的问题。

标签: c linux framebuffer doublebuffered


【解决方案1】:

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

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

无论如何,我希望我已经帮助了将来可能遇到此问题的人。

【讨论】:

  • 感谢链接,但是:drm device '/dev/dri/card0' does not support dumb buffers 在我的 RTX3070 上。但适用于我的英特尔® 超高清显卡 770。
【解决方案2】:

这是一个常见的问题,它是由视频驱动程序的限制引起的。例如,Intel 的 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

【讨论】:

  • Nvidea Quadro 200M 无法处理更大的帧缓冲区似乎不合逻辑。我使用的屏幕是 1600x900,1600x901 的虚拟屏幕尺寸已经给出了错误。有什么方法可以实际查找最大虚拟屏幕尺寸吗?
猜你喜欢
  • 2018-10-19
  • 2016-08-18
  • 2018-07-05
  • 2020-06-30
  • 2012-08-28
  • 1970-01-01
  • 2011-08-13
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多