From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C85CC433EF for ; Mon, 17 Jan 2022 10:26:09 +0000 (UTC) Subject: [psplash][PATCH] psplash: Fix double buffering initialization To: yocto@lists.yoctoproject.org From: "Horn, Michal" X-Originating-Location: Prague, Hlavni mesto Praha, CZ (185.63.97.23) X-Originating-Platform: Linux Chrome 95 User-Agent: GROUPS.IO Web Poster MIME-Version: 1.0 Date: Mon, 17 Jan 2022 02:26:08 -0800 Message-ID: Content-Type: multipart/alternative; boundary="jysNQ92aMU3XyUJdBEGr" List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 17 Jan 2022 10:26:09 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/yocto/message/55889 --jysNQ92aMU3XyUJdBEGr Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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 buffe= r 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/l= inux/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 --- 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 { -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DBG("Virtual resolution set to double")= ; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fb->double_buffering =3D 1; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (ioctl(fb->fd, FBIOPAN_DISPLAY, &fb_= var) =3D=3D -1) { +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fprintf(stderr, "warning: FBIOPA= N_DISPLAY failed, " +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "dou= ble buffering disabled\n"); +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else { +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (fb_var.yres_virtual =3D=3D f= b_var.yres * 2) { +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DBG("Virtual resolution s= et to double"); +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fb->double_buffering =3D = 1; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else { +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fprintf(stderr, "warning:= Doubling virtual " +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 "resolution failed, double buffering disabled\n"); +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } } } } -- 2.25.1 --jysNQ92aMU3XyUJdBEGr Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable
Some fb drivers do not implement double buffering completely or correc= tly.
For example mxsfb driver does not set yres_virtual to double on
initialization, nor it allows its doubling by FBIOPUT_VSCREENINFO ioct= l
call. In such case, the double buffering gets enabled, but psplash fai= ls
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 carefu= lly
that the resolution, virtual buffer resolution and offsets in it are i= n
bounds at (fb_pan_display)[https://elixir.bootlin.com/linux/v4.9.275/s= ource/drivers/video/fbdev/core/fbmem.c#L891].
 
Switching between the front and back buffers is done by switching the<= /div>
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 y= res,
so drawing with the offset set to yres would overrun the buffer. So th= e
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 ca= ll,
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 y= res,
effectively canceling the doubling. But no error is returned in this c= ase,
so it gets silently ignored.
 
# Solution
These two problems can be solved by double checking the yres_virtual o= n
fb_new and disable double buffering in case of doubling yres_virtual f= ails.
 
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 fi= xed framebuffer info");
           goto fail;
         } else {
-          DBG("Virtual resolution set to dou= ble");
-          fb->double_buffering =3D 1;
+          if (ioctl(fb->fd, FBIOPAN_DISPL= AY, &fb_var) =3D=3D -1) {
+            fprintf(stderr, "warning: F= BIOPAN_DISPLAY failed, "
+                   = "double buffering disabled\n");
+          } else {
+            if (fb_var.yres_virtual =3D= =3D fb_var.yres * 2) {
+              DBG("Virtual resolut= ion set to double");
+              fb->double_buffer= ing =3D 1;
+            } else {
+              fprintf(stderr, "war= ning: Doubling virtual "
+                   =   "resolution failed, double buffering disabled\n");
+            }
+          }
         }
       }
     }
-- 
2.25.1
 
--jysNQ92aMU3XyUJdBEGr--