Recently I created a picamera fork with mission statement "to remove need for picamera as well as a connected Raspberry camera" while still allowing to create HDMI overlays. I was able to delete camera.py and 7 other picamera modules and still show HDMI overlay. Because no camera is needed anymore, this works on Pi400 as well:
viewtopic.php?f=32&t=318845&sid=b583a10 ... 0fd2e42344
Yesterday @cleverca22 pointed out that "/opt/vc/src/hello_pi/hello_dispmanx/dispmanx.c" also allows to do HDMI overlays in C. I had worked with dispmanx in the past and was not convinced, but with a comment from him
viewtopic.php?f=32&t=318845&p=1908690#p1908656
I did give it a try today -- and it is not that bad as I remembered.
To get the dispmanx example working, these are the steps needed:
Code: Select all
pi@raspberrypi400:~ $ cd /opt/vc/src/hello_pi/
pi@raspberrypi400:/opt/vc/src/hello_pi $ ./rebuild.sh 2>err >out
pi@raspberrypi400:/opt/vc/src/hello_pi $ cd hello_dispmanx/
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $ ./hello_dispmanx.bin
Open display[0]...
Display is 1360 x 768
Sleeping for 10 seconds...
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $
For making changes, I did copy dispmanx.c to dispmanx.c.orig. Then I modified dispmanx.c, did make and executed "./hello_dispmanx.bin" again.
I did three experiments sofar.
dispmanx is based on rectangle and does not provide functions to draw ellipses. @AndrewFromMelbourne has implemented a lot of additional functionality though. His "SetPixelRGB()"
https://github.com/AndrewFromMelbourne/ ... #L236-L254
would allow to draw circle for crosshairs. Here I changed the circle to a square and get a similar overlay, with only few changes:
Code: Select all
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $ export PS1=$\
$ diff dispmanx.c.orig dispmanx.c.crosshairs
39,40c39,40
< #define WIDTH 200
< #define HEIGHT 200
---
> #define WIDTH 400
> #define HEIGHT 400
106,109c106,110
< FillRect( type, vars->image, pitch, aligned_height, 0, 0, width, height, 0xFFFF );
< FillRect( type, vars->image, pitch, aligned_height, 0, 0, width, height, 0xF800 );
< FillRect( type, vars->image, pitch, aligned_height, 20, 20, width - 40, height - 40, 0x07E0 );
< FillRect( type, vars->image, pitch, aligned_height, 40, 40, width - 80, height - 80, 0x001F );
---
> FillRect( type, vars->image, pitch, aligned_height, 0, 0, width, height, 0x0000 );
> FillRect( type, vars->image, pitch, aligned_height, width/4, height/4, width/2, height/2, 0xFFFF );
> FillRect( type, vars->image, pitch, aligned_height, width/4+1, height/4+1, width/2-2, height/2-2, 0x0000 );
> FillRect( type, vars->image, pitch, aligned_height, 0, height/2, width, 1, 0xFFFF );
> FillRect( type, vars->image, pitch, aligned_height, width/2, 0, 1, height, 0xFFFF );
$
I use Andrews "raspi2png" for creating screenshots that include all HDMI overlays (also raspivid preview window if present). This is "squared crosshairs":
https://github.com/AndrewFromMelbourne/raspi2png
Next I wanted to play with an overlay in changing its layers. This is the small diff do original dispmanx.c, instead of just waiting for 10 seconds to end the HDMI overlay, every second "vc_dispmanx_element_change_layer ()" gets called, switching between layer 2 and 3. In case two HDMI overlays are on same layer, the later updated is on top. For getting a change in display, calling "vc_dispmanx_update_submit_sync()" followed by "vc_dispmanx_update_start( int32_t priority )" is needed:
Code: Select all
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $ diff dispmanx.c.orig dispmanx.c.layers
89c89
< 120, /*alpha 0->255*/
---
> 192, //120, /*alpha 0->255*/
148,149d147
< sleep( 10 );
<
151a150,161
> for(int i=0; i<10; ++i)
> {
> vc_dispmanx_element_change_layer ( vars->update, vars->element, 2 + (i%2) );
> // End an update and wait for it to complete
> ret = vc_dispmanx_update_submit_sync( vars->update );
> assert( ret == 0 );
> // Start a new update, DISPMANX_NO_HANDLE on error
> vars->update = vc_dispmanx_update_start( 10 );
> assert( vars->update != DISPMANX_NO_HANDLE );
> sleep( 1 );
> }
>
162a173
>
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $
I took screenshots with raspi2png every second, and used "pngs2anim"
https://github.com/Hermann-SW/Raspberry ... /pngs2anim
to create an animated .gif playing at 1fps. I started crosshair_overlay.py before (on layer 3), so that dispmanx HDMI overlay shows up (still transparent) above or below Python crosshairs:
Finally I wanted to answer statement raised by @Gavinmc42 in another thread:
I did move the dispmanx overlay on circle around display center, with no delay in between, with 1° moves. It took roughly 18 seconds for 3*360=1080 moves, so a single move was done in rougly 18ms:Someone said moving rects by VPU is very fast
Code: Select all
pi@raspberrypi400:/opt/vc/src/hello_pi/hello_dispmanx $ export PS1=$\
$ diff dispmanx.c.orig dispmanx.c.move
35a36
> #include <math.h>
89c90
< 120, /*alpha 0->255*/
---
> 192, //120, /*alpha 0->255*/
147,149d147
< printf( "Sleeping for 10 seconds...\n" );
< sleep( 10 );
<
151a150,176
> for(int i=0; i<3*360; ++i)
> {
> double r = 250;
> double dx = r * cos(i/180.0*M_PI);
> double dy = r * sin(i/180.0*M_PI);
> vc_dispmanx_rect_set( &dst_rect, dx +( vars->info.width - width ) / 2,
> dy +( vars->info.height - height ) / 2,
> width,
> height );
> vc_dispmanx_element_change_attributes( vars->update,
> vars->element,
> 0, //uint32_t change_flags,
> 2 + (i%2),
> 9, //uint8_t opacity,
> &dst_rect,
> &src_rect,
> 0, //DISPMANX_RESOURCE_HANDLE_T mask,
> 0); //DISPMANX_TRANSFORM_T transform );
>
> // End an update and wait for it to complete
> ret = vc_dispmanx_update_submit_sync( vars->update );
> assert( ret == 0 );
> // Start a new update, DISPMANX_NO_HANDLE on error
> vars->update = vc_dispmanx_update_start( 10 );
> assert( vars->update != DISPMANX_NO_HANDLE );
> }
>
162a188
>
$
https://www.youtube.com/watch?v=h7loeEv8Knw
Current summary:
- dispmanx is OK to create HDMI overlays for all Raspberry PIs in C, but API is quite rectangular
- Python solution retrieved by deleting 8 modules from picamera allows to program HDMI overlays, and with the help of PIL ellipses can be ceated as well
viewtopic.php?f=32&t=318845