BOINC applications can optionally provide graphics. Graphics are displayed either in an application window or in a full-screen window (when acting as a screensaver). There are a couple of ways to do graphics:
In this approach, graphics are generated by a program that is separate from your main application. The main application executes the graphics application, and must kill it when done.
The graphics application can be implemented using the BOINC framework (see below) in which it supplies a render function and leaves the rest to BOINC. In this case it should call boinc_init_graphics() (see below) with a NULL worker function.
Or the graphics application can be implemented from scratch. It will need to monitor the graphics_request message channel (see lib/app_ipc.h) to find out when to open and close windows.
The main and graphics applications typically communicate using shared memory (you can use the functions in boinc/lib/shmem.C for this).
This approach has the advantage that the main application doesn't use graphics libraries, and can execute on systems that don't have these libraries. You can use the same application package for both graphical and non-graphical platforms: on a non-graphical host, the graphics application will exit immediately because the libraries are missing.
In this approach, graphics are generated a thread within your main application. The application must call either
int boinc_init_graphics(void (*worker)()); // for simple applications int boinc_init_options_graphics(BOINC_OPTIONS&, void (*worker)()); // for compound applicationswhere
worker()
is the main function of your application.
Do NOT call boinc_init() or boinc_init_options().
Unix/Linux applications that use graphics should compile all files with -D_REENTRANT, since graphics uses multiple threads.
An application can display a pre-existing image file (JPEG, GIFF, BMP or Targa) as its graphic. This is the simplest approach since you don't need to develop any code. You must include the image file with each workunit. To do this, link the application with api/static_graphics.C (edit this file to use your filename). You can change the image over time, but you must change the (physical, not logical) name of the file each time.
boinc_init_graphics()
creates a worker thread
that runs the main application function.
The original thread becomes the graphics thread,
which handles GUI events and does rendering.
The two threads communicate through application-defined
shared memory structures.
Typically these structures contain information about the computation,
which is used to generate graphics.
You must initialize the shared data structure
before calling boinc_init_graphics()
.
Graphical applications must supply the following functions:
bool app_graphics_render(int xs, ys, double time_of_day);This will be called periodically in the graphics thread. It should generate the current graphic.
xs
and ys
are the X and Y sizes of the window,
and time_of_day
is the relative time in seconds.
The function should return true if it actually drew anything.
It can refer to the user name, CPU time etc. obtained from
boinc_get_init_data()
.
Applications that don't do graphics must also supply a
dummy app_graphics_render()
to link with the API.
void app_graphics_init();This is called in the graphics thread when a window is created. It must make any calls needed to initialize graphics in the window.
void app_graphics_resize(int x, int y);Called when the window size changes.
void app_graphics_reread_prefs();This is called, in the graphics thread, whenever the user's project preferences change. It can call
boinc_parse_init_data_file(); boinc_get_init_data(APP_INIT_DATA&);to get the new preferences.
The application must supply the following input-handling functions:
void boinc_app_mouse_move( int x, int y, // new coords of cursor bool left, // whether left mouse button is down bool middle, bool right ); void boinc_app_mouse_button( int x, int y, // coords of cursor int which, // which button (0/1/2) bool is_down // true iff button is now down ); void boinc_app_key_press( int, int // system-specific key encodings ) void boinc_app_key_release( int, int // system-specific key encodings )
The following global variables control frame rate:
boinc_max_fps is an upper bound on the number of frames per second (default 30).
boinc_max_gfx_cpu_frac is an upper bound on the fraction of CPU time used for graphics (default 0.5).
Several graphics-related classes were developed for SETI@home. They may be of general utility.