Does the RPi 1B rev1 Framebuffer have hardware support for a mouse cursor ?

Jun 25, 2023 Last reply: 3 years ago 43 Replies

Hello all,



I've got a RPi 1B rev1, onto which I've installed "bullseye lite", meaning no GUI of any kind.



I ofcourse wanted to see if I could draw some graphics on it. :-)



I've found that it supports a "Frame Buffer" onto which pixels can be plotted.



I also found the "fb.h" include file, and was able to get FBIOCOPYAREA to work.



Alas, thats as far as I got. Even though the file mentions hardware support for a mouse cursor I've not been able to get that to work. :-(



The file also contains "fb_fillrect" structure, but doesn't show anything about how / where its used.



tl;dr: I could use an example which shows how to use "_iowr()" to get the build-in mouse cursor to work, and would not mind at all if someone knows how to draw a simple rectangle using the same "_iowr()" method.



Regards, Rudy Wieser


RISC OS uses the GPU to draw its hardware pointer. Here's the code:

formatting link
That appears to be using VCHIQ which is the service to send messages to the GPU:
formatting link
RISC OS appears to be using the vc_dispman API to ask the GPU to draw the pointer.

_iowr() is a basic 32-bit I/O write (ie write 32 bits to I/O address

0x....).

The GPU is several levels above this in the stack: you need to craft a message to ask the GPU to do it, using the appropriate API, and then ask something (/dev/vchiq on Linux) to deliver the message.

There may be some support for this stuff in the RPi userland libraries:

formatting link
it's not immediately clear where it might be.

Having said all this, you're on Linux not baremetal so I think a better way would be to use some existing library. I'd have a look at SDL as that might be easier to deal with (SDL 2 is '3D', SDL 1.2 is older and more 2D focused. You might be better starting with SDL 2 to begin with, even if you only want

2D stuff). SDL is designed to be run either in a window or on a bare framebuffer style display.

Theo

If the aim is to go the lowest-level route, then it is possible to send "mailbox" messages to the GPU's proprietary driver directly via /dev/mem, rather than via a driver. Broadcom's routines for this are here:

formatting link
The documentation for Broadcom's GPU firmware isn't public though, so you'd need to look at the code of an existing graphics driver to figure out how to use (some of?) it anyway.

This is the best index that I'm aware of for the various GPU API options:

formatting link

SDL 2 also has a "kmsdrm" driver which in theory might be faster than than the "directfb" framebuffer driver for SDL 1.2 and SDL 2. It uses the kernel's vc4 driver (note that there's a Mesa driver that's also called vc4), which presumably has some way of moving the mouse pointer with the GPU if that acceleration is normally used.

Theo,

Which is why I mentioned the "fb.h" file and its mentioning of having a "_iowr()" function to set up such a cursor. I just can't seem to find enough info to be able to either get it to work or figure out if its unsupported. :-(

Regards, Rudy Wieser

Kev,

Not really. Currently I just want to get it to work thru the available "frame buffer" methods.

The problem is that that "fb.h" file /looks/ to be saying such support is available, but I can't get it to work. As such at this point in time I would just like to know if its supported or not.

I have no problem throwing another number of hours googeling at it trying to figure out what I did wrong and what I need to do instead, but would like to forgo the possibility that its simply not supported (and as such would just be wasting my time, getting more and more frustrated :-( ).

Regards, Rudy Wieser

Björn,

[snip]

Thank you for that code. But I'm looking for something a bit more low-level than that.

I've already written most of what you have there in plain C, but would like to replace some of my own solutions with whats already available as part of the "frame buffer" support.

Hardware instead of a software mouse pointer. Makes the drawing other stuff much easier. The mentioned _iowr() call to draw a (filled) rectangle instead of iterating over all the pixels myself. Perhaps other drawing stuff if available (lines ? (filled) circles ? Anything goes).

Regards, Rudy Wieser

OK right, you're talking about the Linux framebuffer rather than the GPU framebuffer, which the Linux framebuffer writes to. I see now that this is the fb.h file that you mean:

formatting link
I guess this is what you're interested in: /* Draws cursor */ int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);

I guess that _might_ be supported on the Pi via the KMS/DRM driver, but this suggests that it's at least possible for it not to use hardware acceleration:

formatting link
Maybe one of the results here is a good example of using the framebuffer cursor?
formatting link

Kev,

Not quite the same one. Mine seems to be a bit simpler, and starts with :

- - - - - - - - - - - - - - - - - - - - /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _LINUX_FB_H #define _LINUX_FB_H

#include <linux/types.h>

#include <linux/i2c.h>

/* Definitions of frame buffers */

#define FB_MAX 32 /* sufficient for now */

/* ioctls 0x46 is 'F' */ #define FBIOGET_VSCREENINFO 0x4600 #define FBIOPUT_VSCREENINFO 0x4601

- - - - - - - - - - - - - - - - - - - -

Something like it :

- - - - - - - - - - - - - - - - - - - - #define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor)

- - - - - - - - - - - - - - - - - - - -

IOW, I've got the call and the struct(s) (a bit lower in the file), but am struggeling with filling the struct(s) with the correct data. Or maybe I have done that, but my Rpi simply doesn't support it. And I've got no idea how to check for the latter. Frustrating to say the least.

I found that one too, but as the name already suggests, that seems to be for an emulated mouse cursor. That one I already wrote myself. :-)

And although I thought I could at least extract the method with which it draws stuff on the canvas, the part ending with "info->fbops->fb_imageblit(info, image);" has way to much stuf in there that I have no idea what exactly it is doing (using GCC here). :-|

Whoa, 26 pages of it ... That will take me quite some time to get thru it all, even when I skip the C++ snippets.

Thanks for that, I don't think I've ever used that "codesearch" engine.

Regards, Rudy Wieser

OK, this must be it:

formatting link

Yes, and not having programmed for the Linux framebuffer I can't help much myself. But the key thing is that this is the _Linux_ framebuffer, not the hardware framebuffer. So it's hardware independent and there isn't a question over whether your RPi supports it. The same code writing to the Linux framebuffer should display on RPi, PC, or even on a custom display panel that someone's written a framebuffer driver for.

You missed my point. That's in the framebuffer driver code, so when you do all this to move the cursor via the Linux framebuffer, the Linux kernel probably just runs that code to "emulate" a hardware mouse cursor in software. The framebuffer driver on the RPi isn't necessarily good enough to have implemented the hardware acceleration so you might be better off just using your own software mouse cursor code.

I don't know how to rule in/out there being RPi hardware cursor support in the Linux source code. If it's there then it isn't obvious, but these things often aren't. Apparantly in 2014 it wasn't there, because this RPi software engineer published a modified version of the slightly-RPi-accelerated "fbturbo" framebuffer driver which added hardware mouse cursor support:

formatting link
Note that the thread ends before the matching GPU firmware binary was released. Did it get included in a later GPU firmware version, or was it abandoned? If the firmware wasn't released then the thread makes it clear that the hardware cursor didn't work without it.

Or maybe it was released and supported somewhere in the main Linux framebuffer driver that's used now on the RPi. These mysteries are all too hard to figure out, so you'll have to do that yourself.

Gah, I mixed up the kernel framebuffer driver and the X framebuffer driver (both called fbdev). fbturbo is the accelerated X framebuffer driver, and indeed the version with the accelerated cursor support was released and working with the GPU firmware in

2014:
formatting link
So you can't use that fbturbo driver, but _if_ similar code is in the Linux kernel's RPi framebuffer driver somewhere then it might be used. If not, then you might as well draw the cursor with your own code (or use X if you really need the hardware acceleration).

Kev,

Don't be too sure about that. I've seen quite a number of implementations which only code is returning a constant value.

...

Thats the RPi doesn't have hardware support is quite possible, though the "fb.h" file seems to hit at it being present. As such the absense of any way to check (directly or indirectly) for supported features is ... not funny.

Heck, I can't even seem to find any documentation on what the returned value means. And that /really/ bugs me.

I think I've come across that name too, but as with the other bits-and-pieces I found there does not seem to be any testing code around that shows its usage.

I followed the link to james "hwcursor.c" code, and noticed its from 2014. In Rpi time thats pretty-much the stone age era (I'm using bullseye, which is rather recent).

:-) I /know/ its too hard to figure out for me, which is why I posted my question here.

I think I'm going to throw the towel, and just assume that the only support my framebuffer has is copying something from one place on the screen to another, and that everything else - even if I've seen some of them marked as required - needs to be written yourself.

Oh well. Thanks for the help.

Regards, Rudy Wieser

The Pi kernel is a separate tree:

formatting link
one looks quite different to the fb.h in mainline Linux.

The mainline fb.h looks full of 90s-era VGA-related stuff. There's some mention of ARM chips, but they're all 15+ years old.

In general terms, many framebuffers don't support a hardware pointer - they're just dumb framebuffers after all. It looks like support has been added to the Pi version for that.

The Pi hardware doesn't support a hardware pointer either, but AIUI the GPU handles drawing it for you. So it's effectively a fake hardware pointer, it's just drawn by something that isn't the OS.

(traditionally, hardware pointers are drawn on top of the raster scanout. Here the GPU is doing a full image composite instead, so that's not really a 'hardware' pointer, it's just an API call to the GPU)

SFAIK the RPi folks added the 'hardware cursor' support as GPU-side software, to support operating systems like RISC OS which are designed around a hardware pointer. For that (on bare metal) you use the GPU mailboxes to send a VCHIQ message to the GPU.

I think FBIO_CURSOR in that fb.h file is a red herring: it's been there since 29 July 2004, which means the _IOWR is an I/O write that's nothing to do with the Pi, most likely related to some of the VGA-compatible hardware that was in use at the time.

formatting link
I think if you want to use this from modern Linux (not via this legacy framebuffer stuff) you need to interact with the DRM (direct rendering manager) kernel subsystem via the KMS (kernel mode setting) interface:
formatting link
Theo

Theo,

Do you have any (example) code which tells the GPU to do that ? 'Cause I can't seem to find any (might be because I don't recognise it though :-| ).

And if that is so, how does it work with frame buffer (memory) writes ? How does the {whatever} know when it should remove the fake cursor so the image beneath it can be altered ?

Curently I have to disable (remove) my fake cursor before, and than enable (draw) it again after each action which changes the frame buffer memory.

I've gotten that feeling too.

By the way, if you know any other frame buffer manipulation calls (draw (filled) rectangles and circles, draw an image, draw lines(?) ) I would like to hear about them. Even better if you happen to have a link to a Raspberry Pi specific documentation of it. :-)

Regards, Rudy Wieser

I think it would be somewhere in the vc_dispmanx APIs, but I'm not seeing it here:

formatting link
I pointed upthread to the RISC OS code which uses it, but that's not Linux.

It's composited on top by the GPU, ie the framebuffer has no cursor, the GPU draws the cursor on top of the framebuffer when the screen is composited. You just give the GPU a pointer to the cursor bitmap and the X/Y coordinates.

Look at OpenVG which offers 2D graphics operations:

formatting link
Supposedly OpenVG has been dropped from the Pi 4 (which uses a different GPU to 0/1/2/3). These days it's better to use 3D operations (eg OpenGL) for 2D drawing. There are some implementations of OpenVG on top of OpenGL:
formatting link
Theo

Well you said you already saw the fbturbo implementation:

formatting link
OK it's from 2014, but I doubt they would have changed the commands used by the GPU, and they're what matter.

Theo,

I guess I could take a look and see if I can find any "frame buffer" calls in there ... Hmm, a quick look in all the .C files doesn't show any frame buffer related includes.

That suspiciously sounds like mouse pointer hardware support. :-)

Thank you for the link. Though my current objective is to try to find out as much as I can about what "frame buffer" supports.

At some point in the future I might just install OpenGL or alike and bin my own attempts to create something usefull, but today isn't the day.

Hobbyists are weird : they can spend untold hours upon recreating what already exists (even in a better form) and see nothing wrong with it. I'm a hobby programmer. :-)

Regards, Rudy Wieser

Kev,

I did.

The thing is that that is, AFAIK, what "frame buffer" support is build ontop of. With it doing some of the abstractions which would enable a program written using it to run on different hardware configurations.

Going down a level from "frame buffer" support to using the "mailbox" way of sending commands is something I've not yet tried.

Though I might try to rewrite all the "frame buffer" stuff I've currently got using that "mailbox" method. Who knows. Currently my focus is "frame buffer", trying to find out what exactly it offers me and how to use it.

Regards, Rudy Wieser

Traditionally, framebuffer is exactly that. A pointer to an W x H sized block of pixels, which is displayed on the screen. That's it. Nothing else. If you want to draw stuff on it, it's up to you to manipulate the pixels. If you want to double buffer, change the pointer to a different WxH block of pixels.

Some graphics cards (eg VGA) have 'extra stuff' which know about things like fonts or pointers, but that's not the framebuffer, it's down to the VGA or other driver. In the Pi's case that's the VideoCore and the VCHIQ APIs, but they're not standard.

So if you're looking for these things inside the framebuffer code you won't find them. If you do want more stuff you need to explore DRM/KMS (as a generic Linux kernel API) or VCHIQ (for Pi specific things).

Theo

Exactly, and "traditionally" it's actually a hardware address for unaccelerated display of bitmaps via the graphics card. Accelerated things like the mouse cursor are done on top of this. The _Linux_ framebuffer is a pretend version of that, so if any acceleration features did exist, they'd be sort-of a bonus, becuase they're not really the intention, which is a hardware-independent version on the physical framebuffer.

Of course a look at the Framebuffer page on Wikipedia explains all this already.

This is why I originally assumed that R.Wieser _was_ talking about the Pi's hardware framebuffer, instead of the Linux one. He still insists on not specifying which one he's talking about when talking about "the frame buffer stuff" in his posts. Somewhat frustrating.

Theo,

That part I've got down. Drawing lines, (filled) rectangles, (filled) circles, clipping and a software mouse cursor. Still working at filled polygons. Convex works, concave takes some more work.

The whole thing is that the "fb.h" file on my machine hints at support for a few things, like a hardware mouse cursor, drawing a (filled?) rectangle, drawing an image, panning the screen, copying one part of the screen to another part and a few others.

IOW, the same include file which contains the declarations that are needed to be able to create access to such a user-land pixel memory also contains hints to support for other stuff. And the usage of that other stuff is what I'm currently trying to figure out.

I already found them. In many implementations. Though some of them just contain "return -EINVAL;" for a number of the calls. :-|

Currently all I'm doing is looking at the API - and only at a number of implementations to figure out how to use it.

And thats also part of the problem : I have no idea which of those implementations is the one used by bullseye or even if its actually among them. If I had the code it would be rather easy to figure out what, and what isn't supported.

Regards, Rudy Wieser

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required