У меня есть работающее приложение, которое работало напрямую с /dev/fb0 и использовало двойную буферизацию. Приложение прекрасно работало на linux 4.4, но запустив ПО на linux 5.10 я получил сообщение об ошибке:
fbset: ioctl FBIOPUT_VSCREENINFO: Invalid argument
Конкретное место в коде, которое приводит к ошибке:
/* Set virtual display size double the width for double buffering */
device->fb_vinfo.yres_virtual = device->fb_vinfo.yres * 2;
if (ioctl(device->fb_fd, FBIOPUT_VSCREENINFO, &device->fb_vinfo)) {
perror("Error setting variable screen info from fb");
goto handle_ioctl_error;
}
Я так понимаю, что проблема связана с тем, что в linux 5.10 fb эмулируется через DRM и драйвер DRM не поддерживает изменение размера виртуального экрана больше физического. Возможно дело в конкретной реализации drm - sun4i-drmdrmfb.
Вот лог загрузки ядра (linux 5.10 на Allwinner A20):
[ 8.593273] sun4i-drm display-engine: bound 1e00000.display-frontend (ops 0xc0aa5648)
[ 8.601279] sun4i-drm display-engine: bound 1e20000.display-frontend (ops 0xc0aa5648)
[ 8.609606] sun4i-drm display-engine: bound 1e60000.display-backend (ops 0xc0aa4de8)
[ 8.617394] sun4i-drm display-engine: attempt to add DMA range to existing map
[ 8.624981] sun4i-drm display-engine: bound 1e40000.display-backend (ops 0xc0aa4de8)
[ 8.633498] sun4i-drm display-engine: bound 1c0c000.lcd-controller (ops 0xc0aa363c)
[ 8.641837] sun4i-drm display-engine: No panel or bridge found... RGB output disabled
[ 8.649733] sun4i-drm display-engine: bound 1c0d000.lcd-controller (ops 0xc0aa363c)
[ 8.658485] [drm] Initialized sun4i-drm 1.0.0 20150629 for display-engine on minor 0
[ 8.709176] Console: switching to colour frame buffer device 60x50
[ 8.731589] sun4i-drm display-engine: [drm] fb0: sun4i-drmdrmfb frame buffer device
Можно прям в консоли проверить:
# fbset -i
mode "800x480"
geometry 800 480 800 400 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,0/0
endmode
Frame buffer device information:
Name : sun4i-drmdrmfb
Address : (nil)
Size : 1536000
Type : PACKED PIXELS
Visual : TRUECOLOR
XPanStep : 1
YPanStep : 1
YWrapStep : 0
LineLength : 3200
Accelerator : No
попробуем установить виртуальную область меньше физической:
# fbset -v -xres 800 -yres 480 -vxres 800 -vyres 400
Linux Frame Buffer Device Configuration Version 2.1 (23/06/1999)
(C) Copyright 1995-1999 by Geert Uytterhoeven
Opening frame buffer device `/dev/fb0'
Using current video mode from `/dev/fb0'
Setting video mode to `/dev/fb0'
# fbset
mode "800x480"
geometry 800 480 800 400 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,0/0
endmode
вернем все как было:
# fbset -v -xres 800 -yres 480 -vxres 800 -vyres 480
Linux Frame Buffer Device Configuration Version 2.1 (23/06/1999)
(C) Copyright 1995-1999 by Geert Uytterhoeven
Opening frame buffer device `/dev/fb0'
Using current video mode from `/dev/fb0'
Setting video mode to `/dev/fb0'
# fbset
mode "800x480"
geometry 800 480 800 480 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,0/0
endmode
пробуем установить виртуальный экран как 800x960 для double buffering:
# fbset -v -xres 800 -yres 480 -vxres 800 -vyres 960
Linux Frame Buffer Device Configuration Version 2.1 (23/06/1999)
(C) Copyright 1995-1999 by Geert Uytterhoeven
Opening frame buffer device `/dev/fb0'
Using current video mode from `/dev/fb0'
Setting video mode to `/dev/fb0'
ioctl FBIOPUT_VSCREENINFO: Invalid argument
Кто ни будь сталкивался с такой проблемой? Что можно сделать в данном случае - отказаться от double buffering? переписать бекенд на libdrm?
Хотелось бы еще понять почему драйвер drm не поддерживает изменение размера виртуального дисплея…
Спасибо.