Is the FBIO_WAITFORVSYNC ioctl implemented in Rpi's fb?


28 posts   Page 1 of 2   1, 2
by Vanfanel » Tue Oct 02, 2012 11:08 pm
Hello there,

I'm trying to improve the situation regarding tearing on every SDL app I try in the Raspberry Pi framebuffer (no X for me, thanks), so I've been looking in the SDL 1.2.x fbcon backend, and I've found out that the culprit is this function's implementation in SDL_fbvideo.c:

Code: Select all
static void FB_WaitVBL(_THIS)
{
#ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */
        ioctl(console_fd, FBIOWAITRETRACE, 0);
#endif
        return;
}


The comment was already there. Funny but sad...
The correct ioctl to use would be FBIO_WAITFORVSYNC.

I'd like to find out if this ioctl is implemented for the BCM2708 framebuffer, because I doubt it, but I can't find the Raspberry Pi's framebuffer driver in the mainline 3.6 kernel source three: I searched all over linux/src/video, but I couldn't find a single mention to BCM2708 framebuffer (according to raspbian's /sys/class/graphics/fb0/name).

So, can you point me where to look?

Thanks!
Posts: 260
Joined: Sat Aug 18, 2012 5:58 pm
by -rst- » Mon Dec 10, 2012 3:30 pm
Hi Vanfanel!

Did you ever resolve any of this? I have been hitting my head against the vsync (and pan using 'FBIOPAN_DISPLAY') in pure framebuffer code:

Code: Select all
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>

int main(int argc, char* argv[])
{
  int fbfd = 0;
  struct fb_var_screeninfo vinfo_orig;
  struct fb_var_screeninfo vinfo;

  // Open the file for reading and writing
  fbfd = open("/dev/fb0", O_RDWR);
  if (!fbfd) {
    printf("Error: cannot open framebuffer device.\n");
    return(1);
  }
  printf("The framebuffer device was opened successfully.\n");

  // Get variable screen information
  if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
    printf("Error reading variable information.\n");
  }

  // Store for reset
  memcpy(&vinfo_orig, &vinfo, sizeof(struct fb_var_screeninfo));

  // Set variable info
  vinfo.xres = 320;
  vinfo.yres = 240;
  vinfo.xres_virtual = 320;
  vinfo.yres_virtual = 480; // double the physical height
  vinfo.bits_per_pixel = 8;
  if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
    printf("Error setting variable information.\n");
  }

  long int screensize = vinfo.xres * vinfo.yres;
  long int bufsize = vinfo.xres_virtual * vinfo.yres_virtual;
  char *fbp = 0;
  int vs = 0;
  int y = 0;

  // Map fb to user mem
  fbp = (char*)mmap(0, bufsize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);

  if ((int)fbp == -1) {
    printf("Failed to mmap.\n");
  }
  else {
    // draw a blue rect at the upper half of screen
    memset(fbp, 1, screensize / 2);
    // draw a red rect at the lower half of screen
    memset(fbp + screensize / 2, 4, screensize / 2);
    // draw a green rect at the upper half of 2nd screen
    memset(fbp + screensize, 2, screensize / 2);
    // draw a green rect at the lower half of 2nd screen
    memset(fbp + screensize + screensize / 2, 2, screensize / 2);

    sleep(2);

    // change to show lower half
    if (ioctl(fbfd, FBIO_WAITFORVSYNC, 0)) {
      printf("VSync failed.\n");
    }
    vinfo.yoffset = vinfo.yres;
    if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
      printf("Pan failed.\n");
    }

    // wait
    sleep(2);
  }

  // Cleanup
  munmap(fbp, screensize);
  if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo_orig)) {
    printf("Error re-setting variable information.\n");
  }
  close(fbfd);

  return 0;
}


...where both vsync and pan just fail (return -1) :(

The fb driver source here https://github.com/raspberrypi/linux/bl ... m2708_fb.c looks like there would be no support for vsync - but I have not the faintest idea how the Linux drivers are built... Using the dispmanx (vc_dispmanx_update_submit_sync) the vsync seems to work fine.

Regards,

JP
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by dom » Mon Dec 10, 2012 3:37 pm
WAITFORVSYNC does nothing. We added a fake vsync interrupt for RISC OS that can be enabled with fake_vsync_isr=1 in config.txt.
That makes available an ISR when the vync occurs, which would be straightforward to use to make WAITFORVSYNC block until the next vsync.

The FB is single buffered. Can you explain what you are trying to do?
Implement double buffering with a double height buffer, and a wait for vsync, and then a vertical pan?

If you provide some trivial code that tries to do what you want, I can look into supporting it in FB driver.
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3999
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by -rst- » Mon Dec 10, 2012 3:56 pm
Thanks for the reply, Dom!

You describe exactly what my code example above is attempting: double height buffer and pan at vsync to 'flip page'. Is that code trivial enough to be used as a test-case?

I suppose I am not the only one with a shedload of old 8-bit palette graphics code that would be nice to get working and the FBIO* would be the most portable ...of course it would be nice to be able to control the dispmanx resource palette as well (or instead) ;)

Best regards,

JP

P.S. My motivation here is not just getting my own effects etc shown - I think 'poking the pixels' in 256-color byte-per-pixel graphics mode would be very educational (for showing what goes on behind the fancy hw accel libs).
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by -rst- » Fri Apr 05, 2013 11:27 am
Interesting... I managed to fudge together a Linux frame buffer (setting up the double-height buffer and drawing to it) + BCM mailbox (pan display using 'Set virtual offset') 'prototype' to showcase page flipping - it (the 'Set virtual offset') seems to even do it vsync'ed out-of-the-box!

So looks like there would not be need to implement the FBIO_WAITFORVSYNC - just add support for FBIOPAN_DISPLAY in the bcm2708_fb, which should be trivial...

My prototype function:
Code: Select all
// 'Pan display' / 'Set virtual offset'
static unsigned fb_pan_display(unsigned *x, unsigned *y)
{
   int i=0;
   unsigned p[32];
   p[i++] = 0; // size
   p[i++] = 0x00000000; // process request

   p[i++] = 0x00048009; // get physical (display) width/height
   p[i++] = 0x00000008; // buffer size
   p[i++] = 0x00000000; // request size
   p[i++] = *x; // value buffer
   p[i++] = *y; // value buffer 2

   p[i++] = 0x00000000; // end tag
   p[0] = i*sizeof *p; // actual size

   mbox_property(p);
   *x = p[5];
   *y = p[6];
   return p[1];
}

(based on https://github.com/hermanhermitage/vide ... nder-Linux by hermanhermitage, thanks!)

And to use something along:
Code: Select all
// fb setup
...
    vinfo.xres_virtual = vinfo.xres;
    vinfo.yres_virtual = vinfo.yres * 2;
    if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
...

// draw func
void put_pixel(int x, int y, int c)
{
    unsigned int pix_offset = x + y * finfo.line_length;

    // offset by the current page start
    pix_offset += cur_page * page_size;
   
    *((char*)(fbp + pix_offset)) = c;

}


// animation loop
    for (...) {

        // change page to draw to (between 0 and 1)
        cur_page = (cur_page + 1) % 2;
        ...
        vx = 0;
        vy = cur_page * vinfo.yres;
        fb_pan_display(&vx, &vy);
    }       



...I wish I was able to compile the kernel :oops:
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by dom » Fri Apr 05, 2013 11:54 am
-rst- wrote:...I wish I was able to compile the kernel :oops:


http://elinux.org/RPi_Kernel_Compilation ?
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3999
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge
by -rst- » Fri Apr 05, 2013 1:16 pm
dom wrote:
-rst- wrote:...I wish I was able to compile the kernel :oops:


http://elinux.org/RPi_Kernel_Compilation ?


Yes, I have looked at it - does not look overly complicated. Just not enough time to setup a suitable Linux box and all that ...or maybe not enough drive to take the time... then again my RPi is mostly sitting idle :roll:
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by DexOS » Fri Apr 05, 2013 2:55 pm
I have done a Set virtual offset demo for bare metal, but from my basic tests, it seem slower to use mailbox calls, than fast memory copy in assembly.
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by -rst- » Fri Apr 05, 2013 3:07 pm
But then you would need the vsync, wouldn't you?
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by DexOS » Fri Apr 05, 2013 3:32 pm
-rst- wrote:But then you would need the vsync, wouldn't you?

You are right, thats what could be slowing it down, but it seems slower than 60 FPS.
But i will need to do more test to be sure.
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by DexOS » Sat Apr 06, 2013 4:33 pm
DexOS wrote:
-rst- wrote:But then you would need the vsync, wouldn't you?

You are right, thats what could be slowing it down, but it seems slower than 60 FPS.
But i will need to do more test to be sure.

After some test, it seems to be as bad as 10 FPS, but this is in bare metal.
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by -rst- » Sun Apr 07, 2013 2:53 pm
DexOS wrote:After some test, it seems to be as bad as 10 FPS, but this is in bare metal.


Ouch... :shock:

I am getting the exact 60 fps using 'set virtual offset' via the mailbox through ioctl to the char_dev file/node under Raspbian ...which is obviously to be expected as it ties tightly to the display refresh rate.

My tester draws 200 sprites (54x54 pixels size) moving and bouncing off the screen sides in 960x540 resolution and 8 bpp.
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by paulf » Sat May 11, 2013 10:55 pm
-rst- wrote:I am getting the exact 60 fps using 'set virtual offset' via the mailbox through ioctl to the char_dev file/node under Raspbian ...which is obviously to be expected as it ties tightly to the display refresh rate.

My tester draws 200 sprites (54x54 pixels size) moving and bouncing off the screen sides in 960x540 resolution and 8 bpp.


This sounds awesome -rst- - when is it going up on yer blog? ;)
Posts: 10
Joined: Sun May 05, 2013 11:38 pm
by -rst- » Sun Mar 16, 2014 4:37 pm
Phew... it is finally now there in the blog :oops:
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Mon Mar 17, 2014 10:37 am
-rst- wrote:Interesting... I managed to fudge together a Linux frame buffer (setting up the double-height buffer and drawing to it) + BCM mailbox (pan display using 'Set virtual offset') 'prototype' to showcase page flipping - it (the 'Set virtual offset') seems to even do it vsync'ed out-of-the-box!

So looks like there would not be need to implement the FBIO_WAITFORVSYNC - just add support for FBIOPAN_DISPLAY in the bcm2708_fb, which should be trivial...

My prototype function:
Code: Select all
// 'Pan display' / 'Set virtual offset'
static unsigned fb_pan_display(unsigned *x, unsigned *y)
{
   int i=0;
   unsigned p[32];
   p[i++] = 0; // size
   p[i++] = 0x00000000; // process request

   p[i++] = 0x00048009; // get physical (display) width/height
   p[i++] = 0x00000008; // buffer size
   p[i++] = 0x00000000; // request size
   p[i++] = *x; // value buffer
   p[i++] = *y; // value buffer 2

   p[i++] = 0x00000000; // end tag
   p[0] = i*sizeof *p; // actual size

   mbox_property(p);
   *x = p[5];
   *y = p[6];
   return p[1];
}

(based on https://github.com/hermanhermitage/vide ... nder-Linux by hermanhermitage, thanks!)

...I wish I was able to compile the kernel :oops:



you should be able to pan with the normal framebuffer pan ioctl, i've tested that heavily when i was trying to fix android

i believe it was done with FBIOPUT_VSCREENINFO and changing the yoffset
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm
by -rst- » Tue Mar 18, 2014 10:09 am
cleverca22 wrote:you should be able to pan with the normal framebuffer pan ioctl, i've tested that heavily when i was trying to fix android

i believe it was done with FBIOPUT_VSCREENINFO and changing the yoffset


Hmm, maybe that has been changed at some point during the last year - I am sure I did test all possible options with the fb ioctls last April - will need to test again. One of the cases where I would very much like to be proven wrong ;)
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Tue Mar 18, 2014 1:22 pm
https://github.com/raspberrypi/linux/blob/rpi-3.10.y/drivers/video/bcm2708_fb.c#L284

this appears to be the main function responsible for changing things like the yoffset, it was working fully a few months ago when i was testing some android stuff out

and on line 297 it sends all the config params to the blob
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm
by -rst- » Tue Mar 18, 2014 3:35 pm
The same line of code was there in 3.6 https://github.com/raspberrypi/linux/bl ... _fb.c#L214 and I found my tester code with file timestamp on 06/03/2013:

Code: Select all
...
  vinfo.xres = 320;
  vinfo.yres = 240;
  vinfo.xres_virtual = 320;
  vinfo.yres_virtual = 480;
  vinfo.bits_per_pixel = 8;
  ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo));

...
        // change to show other half
        vinfo.yoffset = cur_half * 240;
        ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo);
        cur_half = (cur_half + 1) % 2;
...


...which I am fairly sure did not work - that code should be correct?. Then again, maybe it has been changed in the blob code... I don't the my RPi here with me, but will try this out later.
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Tue Mar 18, 2014 3:37 pm
if you could paste the full source of that test app, i can run it on mine and verify things
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm
by -rst- » Tue Mar 18, 2014 5:05 pm
This one uses FBIOPAN_DISPLAY: https://github.com/rst-/raspberry-compo ... fbtestXI.c - could just replace with FBIOPUT_VSCREENINFO

*Update*

Tested now with:
Code: Select all
        // switch page
        vinfo.yoffset = cur_page * vinfo.yres;
        //vinfo.activate = FB_ACTIVATE_VBL;
        vinfo.activate = FB_ACTIVATE_NOW;
        //if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
        if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
            printf("Error panning display.\n");
        }


...to no avail - changing the screen info does not come back with an error like panning, but it just resets the screen - yoffset stays at 0. Tested also other vinfo.activate options...
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Wed Mar 19, 2014 2:40 pm
Code: Select all
diff --git a/fb/fbtestXI.c b/fb/fbtestXI.c
index 39a2613..83bc68e 100644
--- a/fb/fbtestXI.c
+++ b/fb/fbtestXI.c
@@ -106,8 +106,9 @@ void draw() {
         
         // switch page
         vinfo.yoffset = cur_page * vinfo.yres;
+       printf("cur_page %d, yoffset %d, yres %d, virty %d\n",cur_page,vinfo.yoffset,vinfo.yres,vinfo.yres_virt
         vinfo.activate = FB_ACTIVATE_VBL;
-        if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
+        if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
             printf("Error panning display.\n");
         }
         


Code: Select all
cur_page 0, yoffset 0, yres 270, virty 540
cur_page 1, yoffset 270, yres 270, virty 540
cur_page 0, yoffset 0, yres 270, virty 540
cur_page 1, yoffset 270, yres 270, virty 540


at a glance, this code appears to work, the screen flashes back and forth between fbcon and something else, i think fbcon is confused by the pan is being changed

fbcon appears to be redrawing itself over things, need to get exclusive access somehow
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm
by -rst- » Wed Mar 19, 2014 5:23 pm
Ah yes, if I do this:

Code: Select all
void draw() {

        // fill page 1 - blue
        fill_rect(0, 0, vinfo.xres, vinfo.yres, 1);

        // fill page 2 - green
        fill_rect(0, vinfo.yres, vinfo.xres, vinfo.yres, 2);

        sleep(2);

        // switch page
        vinfo.yoffset = vinfo.yres / 2; //cur_page * vinfo.yres;
        //vinfo.activate = FB_ACTIVATE_VBL;
        vinfo.activate = FB_ACTIVATE_NOW;
        //if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
        if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
            printf("Error panning display.\n");
        }

        sleep(2);

        // fill page 2 - cyan
        fill_rect(0, vinfo.yres, vinfo.xres, vinfo.yres, 3);


        sleep(2);
}


...I get first a blue screen for 2 s, then whatever was on the console for 2 s, then cyan - so the FBIOPUT_VSCREENINFO with yoffset sort of works... Only now I realise why I did not notice this before: I was starting the tester app from a SSH session with RPi 'main' display in sleep mode, so the console buffer was empty :?
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Wed Mar 19, 2014 9:20 pm
i have noticed, that when the console goes into sleep mode, it blanks the entire thing out

however, that has no impact on dispmanx layers, and it never activates the power save mode in the monitor

i still think we need to tell fbcon to stop redrawing things, but it may if you just turn the cursor blink and local echo off

i was running things over ssh, so the login prompt was still blinking a cursor and redrawing junk over the animation
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm
by -rst- » Fri Mar 21, 2014 11:53 am
Yes, deactivating the fbcon might help - will try that. Would be slightly embarrassing if it was as simple as disabling the cursor, which I seem to have done in the mailbox version https://github.com/rst-/raspberry-compo ... btestXII.c ...

*Update*

And tested... switching the cursor to graphics mode (KD_GRAPHICS) does get rid of the redrawing of fbcon contents... but unfortunately it appears that the FBIOPUT_VSCREENINFO clears the framebuffer (with the sliding rectangle code of fbtestXI.c I see only a blank screen - with the above code snippet I get: blue screen 2 s, blank 2 s, then cyan) :(
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 898
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by cleverca22 » Fri Mar 21, 2014 3:51 pm
but unfortunately it appears that the FBIOPUT_VSCREENINFO clears the framebuffer


this may explain why i could never get it to work in android!!!
Posts: 168
Joined: Sat Aug 18, 2012 2:33 pm