Can I direct the output to Framebuffer 1

Hi Ray,

I am playing with graphics on a small TFT screen attached to a Raspberry Pi.

Using the fbtft drivers, I can make this screen appear to the Raspberry Pi as /dev/fb1 (the HDMI output is /dev/fb0). Is there a way I can re-direct the output of programs written using raylib to /dev/fb1? or is this a limitation of OpenGL?

Morph

Comments

  • edited September 2016
    Hi Morphology,

    Just investigated this possibility. I started looking for the place where graphic device is initialized by raylib for RPI (based on official RPI OpenGL ES samples); here it is that point: https://github.com/raysan5/raylib/blob/develop/src/core.c#L1680

    Looking on the internet for an answer, I found some references:
    http://stackoverflow.com/questions/19485805/raspberry-pi-egl-how-to-use-fb1
    https://www.raspberrypi.org/forums/viewtopic.php?f=67&t=58952
    https://www.opengl.org/discussion_boards/showthread.php/182958-EGL-How-to-bind-EGL_DEFAULT_DISPLAY-to-fb1

    A bit discouraging though... it seems OpenGL is limited in that sense...

    Please, let me know if you find some solution and I'll try to add that feature to raylib.
  • edited September 2016
    Investigating a bit more on this issue, I see a couple of possible solutions:

    1) Retrieve OpenGL ES framebuffer with glReadPixels() (copy pixels data from GPU VRAM to CPU RAM, the same I do to take a screenshot), once the frame is on RAM, it can be copied anywhere (fb1). The problem is that glReadPixels() is a very slow function and application frame drop could be considerable... It should be tested but I think that for a small screen resolution (640x480) it could be viable.

    2) raylib offers a set of functions to operate directly over Image data (no GPU accelerated, kind-of software 2d rendering, probably not much optimized). Depending on project requirements and kind of interface to draw, GPU hardware could be completely ignored and just use raylib to draw to Image struct and then manually blit that Image into fb1. Probably also slow but it could work... Check available Image manipulation functions: https://github.com/raysan5/raylib/blob/develop/src/raylib.h#L764

    If you find any other solution, please let me know!

    If you decide to go for any of the above solutions, I can try to give you some support adding additional required functions to raylib. :)

    UPDATE:

    Some more investigation... looking for faster alternative to glReadPixels(): https://vec.io/posts/faster-alternatives-to-glreadpixels-and-glteximage2d-in-opengl-es
  • Ray, thank you for looking into this. It would appear from reading those references that I will not be able to use OpenGL ES at all, and therefore cannot benefit from graphics hardware acceleration, which was the main reason I was interested in Raylib.

    In my app I am already writing directly to FB1, and have written functions to draw various graphics primitives (rectangles, circles), display Images and simple text.

    The problem I have is that the RPi hardware seems to stop me writing to FB1 at certain times. If I update lots of pixels in a fast loop, I find that my software loop will pause periodically (only for a few ms, and probably only when the Pi is updating the display via SPI), but it is enough to interrupt my application, which I need to run in real time.

    I had hoped that Raylib would give me the ability to speed up the Graphical side of my app, but it seems that is not going to be possible.

    The alternative approach I will try is as described in http://raspberrycompote.blogspot.co.uk/2015/01/low-level-graphics-on-raspberry-pi-part.html which is to use a double-height framebuffer and flip between them tied to vSync in order to avoid flicker. My concern is that the ioctl call to wait for vsync: ioctl(fbfd, FBIO_WAITFORVSYNC, 0); will also cause my code to pause.

    I definitely think some of your Text functions (ImageText, ImageDrawText etc) could be very useful - at the moment I am limited to simple bitmapped fonts

    Morph
  • Hi, I just dropped by to post an update to my comment, above.

    After spending a while writing various functions to write directly to fb1 on the Raspberry Pi, I have actually abandoned that approach as I found the following gave me much better performance:

    - Use Raylib to write to fb0
    - Us raspi2fb to mirror fb0 to fb1

    It seems that the benefits of hardware acceleration using Raylib to write to fb0 outweigh the additional time that raspi2fb takes to mirror the default framebuffer to the secondary one.

    This means I can use Raylib to develop my app on the usual HDMI output of the Pi, and then mirror this to the TFT screen accessed via fb1. Plus, of course, Ray has already done all of the hard work creating this excellent library!

    Morph
  • Hi Morphology! Thank you very much for the feedback!

    It would be great if you could share the code you use to do that or some usage example, I'm sure other users would find that code very useful! I can try adding a sample into raylib repo. :)

    Ray
  • Hi Ray,

    there is no particular magic to what I am doing. The first stage is to get the TFT screen working with the Raspberry Pi. In my case I am using one based on the ili9340 TFT controller, with an ads7846 touchscreen controller. These use SPI Bus 0 and 1, so SPI has to be enabled.

    Nortro's TFT drivers are now built into the latest Raspberry Pi core, so to get this screen working on the Pi, you just need to edit /etc/rc.local and add the following just above the existing script that prints the IP address:

    modprobe fbtft_device custom name=fb_ili9340 buswidth=8 speed=16000000 bgr=1 gpios=reset:27,dc:22 rotate=270

    Note: bgr=1 is necessary on my TFT as red & blue were reversed. rotate=270 because of the orientation of the screen. If not needed, leave them off.

    Edit /boot/config.txt and do the following:

    Take the comment off the line dtparam=spi=on

    Add the following in the sections entitled
    #additional overlays and parameters are....

    dtoverlay=ads7846,penirq=17,speed=16000000,xohms=100,swapxy=1

    again, swapxy was because of my screen orientation.

    This gets my TFT working, and I can test it by typing the following at the command line, which directs the console output to fb1:

    con2fbmap 1 1

    and back again with

    con2fbmap 1 0

    Then, to mirror fb0 to fb1 continuously I use raspi2fb available from github, along with build and install instructions:

    https://github.com/AndrewFromMelbourne/raspi2fb

    Finally, I added the following lines to /boot/config.txt so that the aspect ratio of the HDMI screen exactly matches that of the TFT (320 x 240) - otherwise you'll get dead bands down the side of the TFT. This sets the HDMI output to 1280x960 which is the same aspect ratio as 320x240:

    hdmi_group=2
    hdmi_mode=32
    hdmi_cvt 1280 960 60 1 0 0 0

    This is when developing, so that with X running I still get a high resolution display for writing code etc., however, if all I am doing is running the Pi with JUST the TFT attached, then I use the following settings in /boot/config.txt which sets the default HDMI resolution to 320 x 240 BUT NOTE: my main HDMI monitor cannot display that resolution, so if I need to change it back, I have to edit /boot/confix.txt using the TFT display, which can be quite a challenge!

    #hdmi_group=2
    #hdmi_mode=32
    hdmi_cvt 320 240 60 1 0 0 0

    Once that is all done, and you've re-booted, start raspi2fb as a daemon by typing the following:

    raspi2fb --daemon

    And the HDMI should be mirrored to the TFT. The default framerate for raspi2fb is 10fps, so there is a bit of a lag between what happens on fb0 (HDMI output) and the mirrored version on fb1, but it is fine for my purposes. The important point is that I can then run RayLib as usual, and whatever I output to fb0 is automatically mirrored to fb1.

    As I mentioned above, this actually gives me better performance than my raw graphics routines that wrote directly to fb1. I cannot really explain this, though I suspect that the Linux Copy On Write may have something to do with it??

    Cheers.

    Morph.
  • Note: the line starting with modprobe line-wrapped. The rotate=270 should all be part of the same line.
  • Hi Morphology! Thank you very much for the explanation! :smile:

    Just added it to raylib Wiki: https://github.com/raysan5/raylib/wiki/Redirect-raylib-output-to-Framebuffer-1
Sign In or Register to comment.