Thanks to everyone that helped. I thought I would post my final solution to help others that might read this question. It's basically the code from dispmanx
with a few of the things that I learned.
First, in order to compile you will need to add the following include directories to your makefile
+= /opt/vc/include
+= /opt/vc/include/interface/vcos/pthreads
and the following library.
-Lopt/vc/lib/ -lbcm_host
Now include the "bcm_host.h"
file in your source and the following structure definition:
typedef struct
{
DISPMANX_DISPLAY_HANDLE_T display;
DISPMANX_MODEINFO_T info;
void *image;
DISPMANX_UPDATE_HANDLE_T update;
DISPMANX_RESOURCE_HANDLE_T resource;
DISPMANX_ELEMENT_HANDLE_T element;
uint32_t vc_image_ptr;
} RECT_VARS_T;
static RECT_VARS_T gRectVars = { 0 };
When the program starts, call the bcm_host_init()
function to initialize the video core.
My goal was to display full screen, solid color test patterns. I simplified down the dispmanx
example and moved the FillRect
function code into the following source. I realize my current method to generate the test pattern is not optimal in terms of performance, but I left it in case I add more complicated test patterns in the future (us565RGB
is the color pattern).
RECT_VARS_T *vars;
VC_RECT_T src_rect;
VC_RECT_T dst_rect;
VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
255, /*alpha 0->255*/
0 };
vars = &gRectVars;
vars->display = vc_dispmanx_display_open( 0 );
vc_dispmanx_display_get_info( vars->display, &vars->info);
vars->image = calloc( 1, vars->info.width * vars->info.height * 2);
/* Construct the test pattern */
uint16_t *line = (uint16_t *) vars->image;
for ( int row = 0; row < vars->info.height; row++ )
{
for ( int col = 0; col < vars->info.width; col++ )
{
line[col] = us565RGB;
}
line += vars->info.width;
}
vars->resource = vc_dispmanx_resource_create( VC_IMAGE_RGB565,
vars->info.width,
vars->info.height,
&vars->vc_image_ptr );
vc_dispmanx_rect_set( &dst_rect, 0, 0, vars->info.width, vars->info.height);
vc_dispmanx_resource_write_data( vars->resource,
VC_IMAGE_RGB565,
vars->info.width * 2,
vars->image,
&dst_rect );
vars->update = vc_dispmanx_update_start( 10 );
vc_dispmanx_rect_set( &src_rect, 0, 0, vars->info.width << 16, vars->info.height << 16 );
vc_dispmanx_rect_set( &dst_rect, 0, 0, vars->info.width, vars->info.height );
vars->element = vc_dispmanx_element_add( vars->update,
vars->display,
2000, // layer
&dst_rect,
vars->resource,
&src_rect,
DISPMANX_PROTECTION_NONE,
&alpha,
NULL, // clamp
VC_IMAGE_ROT0 );
vc_dispmanx_update_submit_sync( vars->update );
To clear the test pattern, I call the following code:
if ( gRectVars.image != NULL )
{
gRectVars.update = vc_dispmanx_update_start( 10 );
vc_dispmanx_element_remove( gRectVars.update, gRectVars.element );
vc_dispmanx_update_submit_sync( gRectVars.update );
vc_dispmanx_resource_delete( gRectVars.resource );
vc_dispmanx_display_close( gRectVars.display );
memset( &gRectVars, 0x00, sizeof( RECT_VARS_T ) );
}
Finally, I've observed that you do not want to call the code that creates a test pattern without clearing the previous test pattern. If you do, the previous test pattern will be "stuck" on the display and the only way to remove it appears to be rebooting the Raspberry Pi. You also don't want to exit the program without clearing the test pattern because, again, it will leave the test pattern on the display and a reboot appears to be the only way to fix it. Unfortunately clearing the test pattern and switching to another one means you'll see the first pattern, then the live display (command prompt or GUI), and then the next test pattern. I experimented a bit with modifying the active test pattern, but abandoned that effort due to time and the lack of documentation on the API.
Hope this helps!