Invalid argument error when setting yres_virtual to fb_var_screeninfo

I am trying to create a linux application that is written directly to framebuffer / dev / fb0. To make it double-buffered, I try to make the virtual screen 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 does not execute ioctl(fb0, FBIOPUT_VSCREENINFO, &screeninfo_var) error messages with an invalid argument. When deleting the line screeninfo_var.yres_virtual = screeninfo_var.yres * 2; it works fine (but without double buffering).

Does anyone see what I'm doing wrong here?

+4
source share
2 answers

This is a common question, and this is due to the limitation of the video driver. For example, the Intel 810 chipset only allows 640x480 resolution, and Broadcom limits the width to no more than 1200 ( http://www.raspberrypi.org/phpBB3/viewtopic.php?f=66&t=29968 ).

There is not much you can do here if you do not change the driver itself or the video card (if possible).

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

There is a hint here: http://www.mail-archive.com/ debian-russian@lists.debian.org /msg27725.html

0
source

To save anyone a headache in the future, there is a way to double the buffer correctly using low-level graphics in Linux (e.g. / dev / fb0). However, in this thread: https://forum.odroid.com/viewtopic.php?f=55&t=8741 it is impossible to truly double the framebuffer buffer by creating a virtual framebuffer with twice the size of the original one (I read that raspberry PI may be an exception from this rule, because it is supported by another driver).

The correct way to double the buffer using low-level graphics on linux is to go through libdrm (or / dev / dri / card0). There is a very good example of what I followed: https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c . Converting my / dev / fb 0 code to / dev / dri / card0 is not very difficult.

In any case, I hope I helped someone here who might run into this in the future.

0
source

All Articles