[psplash] psplash: Fix double buffering initialization

Message ID x5Mp.1642415168178512138.GgEV@lists.yoctoproject.org
State New
Headers show
Series [psplash] psplash: Fix double buffering initialization | expand

Commit Message

Horn, Michal Jan. 17, 2022, 10:26 a.m. UTC
Some fb drivers do not implement double buffering completely or correctly.
For example mxsfb driver does not set yres_virtual to double on
initialization, nor it allows its doubling by FBIOPUT_VSCREENINFO ioctl
call. In such case, the double buffering gets enabled, but psplash fails
to display every second frame with error
*psplash_fb_flip: FBIOPAN_DISPLAY failed: Invalid argument*.

# Technical details:

## Why every second frame gets thrown?

Panning the display by FBIOPAN_DISPLAY ioctl is always checking carefully
that the resolution, virtual buffer resolution and offsets in it are in
bounds at (fb_pan_display)[https://elixir.bootlin.com/linux/v4.9.275/source/drivers/video/fbdev/core/fbmem.c#L891].

Switching between the front and back buffers is done by switching the
yoffset between 0 and yres values. For double buffering, the complete buffer
has yres_virtual size and it must be double of yres.

But in case of the mxsfb driver, the yres_virtual is always equal to yres,
so drawing with the offset set to yres would overrun the buffer. So the
panning is stopped and error *Invalid argument* is returned.

## Why doubling the yres_virtual fails?

yres_virtual is supposed to be doubled by FBIOPUT_VSCREENINFO ioctl call,
that at some point calls the (mxsfb_check_var)[https://elixir.bootlin.com/linux/v4.9.275/source/drivers/video/fbdev/mxsfb.c#L269]
function, which for some reason always sets the yres_virtual back to yres,
effectively canceling the doubling. But no error is returned in this case,
so it gets silently ignored.

# Solution
These two problems can be solved by double checking the yres_virtual on
fb_new and disable double buffering in case of doubling yres_virtual fails.

Signed-off-by: Michal Horn <michalhorn@eaton.com>
psplash-fb.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)



diff --git a/psplash-fb.c b/psplash-fb.c
index 2babb5f..1b73807 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -213,8 +213,18 @@  psplash_fb_new (int angle, int fbdev_id)
perror(" Error getting the fixed framebuffer info");
goto fail;
} else {
-          DBG("Virtual resolution set to double");
-          fb->double_buffering = 1;
+          if (ioctl(fb->fd, FBIOPAN_DISPLAY, &fb_var) == -1) {
+            fprintf(stderr, "warning: FBIOPAN_DISPLAY failed, "
+                    "double buffering disabled\n");
+          } else {
+            if (fb_var.yres_virtual == fb_var.yres * 2) {
+              DBG("Virtual resolution set to double");
+              fb->double_buffering = 1;
+            } else {
+              fprintf(stderr, "warning: Doubling virtual "
+                      "resolution failed, double buffering disabled\n");
+            }
+          }