invalid argument error when setting yres_virtual in fb_var_screeninfo
Asked Answered
C

2

5

I'm trying to make an application for linux that writes directly to the framebuffer /dev/fb0. In order to make it double buffered I try to make the virtual screen be double the size of the screen. This is the program I wrote:

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!");
}

The program failes on ioctl(fb0, FBIOPUT_VSCREENINFO, &screeninfo_var) reporting the error invalid argument. When removing the line screeninfo_var.yres_virtual = screeninfo_var.yres * 2; it runs fine (but without double buffering).

Does someone see what I do wrong here?

Cowie answered 25/2, 2013 at 16:26 Comment(1)
did you ever figure this out? I am currently having a similar problem.Bibby
A
1

To save anyone a headache in the future, there is a way to properly double buffer using low level graphics on linux (such as /dev/fb0). However per this thread: https://forum.odroid.com/viewtopic.php?f=55&t=8741 it is not possible to truly double buffer the framebuffer by creating a virtual framebuffer of double the size of the original one (I've read that the raspberry PI might be an exception to this rule because it is backed by a different driver).

The right way to double buffer using low level graphics on linux is to go through libdrm (or /dev/dri/card0). There is a really nice example that I followed myself here: https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c. It wasn't very hard to convert my /dev/fb0 code to /dev/dri/card0 code.

Anyways I hope I've helped someone out here who might come across this in the future.

Axle answered 7/4, 2018 at 16:29 Comment(1)
Thx for the link, but: drm device '/dev/dri/card0' does not support dumb buffers on my RTX3070. But works on my Intel® UHD Graphics 770.Irrigate
C
0

This is a common question and it is caused by the limitation of the video driver. E.g., Intel's 810 chipset only allows 640x480 resolution and the Broadcom's limit the width to no more than 1200 (http://www.raspberrypi.org/phpBB3/viewtopic.php?f=66&t=29968).

Not much you can do here, unless you change the driver or the videocard itself (if possible).

EDIT: if you are on a PC, try using the vesafb, not the intel's driver.

There's a hint here: http://www.mail-archive.com/[email protected]/msg27725.html

Contain answered 25/2, 2013 at 17:15 Comment(1)
It seems illogical that a Nvidea Quadro 200M whould not be capable of handling a bigger framebuffer. The screen I use is 1600x900, a virtual screen size of 1600x901 already gives the error. Is there some way to actually look up the maximum virtual screen size?Cowie

© 2022 - 2024 — McMap. All rights reserved.