The goal of these notes is to write down what I know about screensaver graphics for Unix computers using the X11 window system. As I'm putting this together I don't have any particular recomendations, but I'm hoping that writing this all down will result in a clear path to how to best develop the screensaver code for BOINC for Linux.
This page contains a collection of what I've learned about screensavers for Unix and X11, and some ideas on how best to proceede to create the screensaver code for BOINC for Unix systems.
Last modified: 16 March 2010
This document is still a draft and is quite incomplete.
The OpenGL library contains basic rendering functions, but a
collection of commonly used but more complicated functions is provided
by an additional library, called the GL Utilities (GLU).
The GLU library is the same for all platforms.
All of the GLU functions are written in terms of OpenGL primatives.
OpenGL handles graphics rendering, but it does not deal with
system-dependent aspects of dealing with the windowing system, such as
creating, resizing or destroying a window, getting input from the
keyboard or mouse, or writing text to the screen (ie., fonts).
These tasks are handled by different libraries written for the
different platforms: For Windows there is wgl, for the Mac there is
agl, and for X11 there is glX.
A convenient way to write OpenGL programs which are portable across
all platforms is to use a library written by Mark J. Kilgard called
the OpenGL Utility Toolkit, GLUT.
GLUT presents a common API for the programmer but takes care of the
system-dependent tasks of opening or managing windows, keyboard and
mouse input, and text.
GLUT on Windows is implemented using wgl, while on a Mac it is
implemented using agl, and on X11 it it implemented with glX.
GLUT also takes care of other common graphics tasks, such as creating
the event loop and handling windowing events.
GLUT makes it much easier to write OpenGL programs quickly while
focusing on the graphics, not the underlying structure to support
graphics with event processing, and your programs are more readily
portable.
BOINC presently uses GLUT for graphics on Linux and the Mac.
BOINC presently does not use GLUT on Windows, except for some
reference to GLUT fonts in the file gutil.C.
Although GLUT provides many advantages, there are also some drawbacks.
One is that the way keyboard input is handled in GLUT is slightly
different from how it is handled (without GLUT) on Windows, and is
somewhat restrictive.
On Windows a keyboard event routine is called whenever an individual
key is pressed (or released), and the keycode for that key is
passed as an argument.
With GLUT, the key-pressed routine is only invoked when certain keys
are pressed, and in this case the character code is passed as
an argument.
The difference is subtle but important.
For example, on Windows if you press and hold the control key and then
press the C key, the key-pressed routine is called first for the
control key, then for the C key.
Using GLUT on Linux, the key-pressed routine is only called once,
sending the character code for ctrl-C, only after the C key has been
pressed.
The BOINC code for Windows now has a feature which allows one to hold
down the control key
and then manipulate the screensaver image with the mouse or keyboard,
without terminating the screensaver.
(Actually, this is only possible right now if you have selected "Run
Always", but it may be possible to extend this feature even to when
"Run according to user preferences" is selected.
This will likely require a change to the BOINC core client, not just
the graphics routines used by the application.)
In Linux, since GLUT is used for keyboard input, it is not possible to
sense when just the control key has been pressed, so this screensaver
manipulations feature is not possible.
GLUT also has problems with creating a full-screen borderless window
on some X11 desktops.
You get a window the size of the screen, but it has a border and it
does not exactly cover the screen, but instead exends off the screen
onto the next desktop segment (this is observed with fvwm2).
It turns out that in X11 there are some conventions used by
screensaver programs like xscreeensver and desktop environments and
window managers such as Gnome, KDE, and fvwm, and GLUT does not pay
any attention to these conventions.
Thus it may be desirable to abandon GLUT for Unix screensaver graphics
for BOINC, and instead replace the relevant code with the appropriate
glX code, or with code based on SDL (the Simple Directmedia Layer).
Potential options are discussed further below.
It should be noted for the discussion below that each platform also
has it's own graphics functions which are a part of the native window
system, separate from OpenGL.
X has it's own graphics API which is separate from OpenGL on X.
Windows has GDI, the Graphics Device Interface.
Mac has it's own graphics system, called Aqua(?).
But each also has an API for OpenGL on that platform.
Each graphics program used by xscreensaver is called a 'hack'.
There are about 180 graphical hacks included in the latest
xscreensaver distribution.
The graphical hacks are modular.
Each is compiled with common code for the main program, resulting in a
separate standalone program.
If you just run this standalone program from the command line then a
new window pops up on your screen containing the graphics demo.
If you run one of the programs with the -root flag then the
graphics appear in the "root" window, which in X11 is the rearmost
window.
However, if the program is run with the -root flag by the xscreensaver
daemon then they appear in a full screen window in front of all other
windows -- thus a "screen saver" graphic.
The graphical hacks are also compiled with a special header file,
vroot.h, written by Andreas Stolcke, which redefines the X11
macros RootWindow and DefaultRootWindow to make them look for a
virtual root window.
If none is found, the ordinary root window is returned which retains
backward compatibility with standard window managers.
The whole idea of this "vroot hack" is to leverage backward
compatibility with existing graphics programs and window managers.
Many graphics programs already drew to the root window if the
-root flag was given on the command line, and several window
managers put screensaver graphics in a virtual root window.
The "vroot.h" hack just brought the two ideas together.
More modern window managers still "play nice"
with virtual root windows.
Thus xscreensaver works with the Gnome and KDE desktop environments,
and the twm, fvwm1 and fvwm2 window managers.
Some of these may also have other mechanisms for indicating that a
window is to be considered a screensaver window.
In any case, a Unix screensaver for BOINC should therefore utilize the
same mechanism(s).
My inability to get this to work may be due to my inexperience with
X11 graphics.
However, I recall finding comments in the xscreensaver code saying it
wasn't likely that GLUT graphics could ever be made to work with
xscreensaver.
If Jamie Zawinski can't do it then I doubt that I can, at least not
yet.
So right now I'm not pursuing this idea any further.
If we go this way then the easiest way to do it would be to also
emulate the glX code which already exists in xscreensaver.
In particular, the event loop and window initialization are in the
file screenhack.C, with the GL code enabled when the macro
USE_GL is defined.
Some additional functions required just for GL are in the file
xlock-gl.C, and some important headers are in
xlockmore.h and xlockmoreI.h, though not everything
in those files is actually need.
The Microsoft Developers Network site has some useful notes
on the correspondence between glX and wgl/WIN32 functions
here.
(You probably have to select the item "GLX and WGL/Win32" after you
get there.)
An alternative to GLUT which might do the job without requiring us to
rewrite the event loop and window initialization is to use SDL [www.libsdl.org].
I've just learned about this library so I don't know if it would be
easier to code with this library or if it handles keyboard input and
full screen windows the way we need them.
It should be investigated.
SDL is available for Windows, Mac and Unix, so anything written with
SDL should be portable across all these platforms.
I haven't quite gotten it working yet, but as of this writing I feel
like I'm close. Here is how it works:
Overview of BOINC graphics with OpenGL and GLUT
BOINC screensaver graphics are written using OpenGL, which has several
advantages.
OpenGL is common to a wide variety of platforms, including the primary
BOINC platforms: Windows, Mac, and Linux.
OpenGL, or at least an important subset of it, is also implemented in
hardware in many computer graphics cards, which means the graphics can
run on a computer's GPU rather than the CPU, allowing the CPU to work
on the computation thread, or at least taking some load off the CPU.
xscreensaver
Xscreensaver is a popular and versitile screensaver framework
for Unix computers which use the X11 window system.
It was written by Jamie Zawinski, and the code is freely available for
download from www.jwz.org/xscreensaver
The primary component of xscreensaver is a program which runs in the
background and waits until the keyboard and mouse are idle for a given
period.
It then runs one of a variety of graphics demos, chosen at random, until
someone uses the mouse or keyboard.
The Virtual ROOT window
The way xscreensaver puts the graphics into this frontmost window is a
bit clever, but also a bit complicated.
There are simple, standard macros in X11 to determine the root
window for a given X11 screen, and all the hacks use one of these when the
-root flag is given.
This was a common thing for many X11 graphics programs to do.
When xscreensaver wants to display the screensaver it opens a
borderless window the size of the screen and in front of all other
windows, and it gives this window a special property which marks it as
the "virtual root" window.
GLUT and the VROOT window?
Since BOINC currently uses GLUT to create the screensaver window I
have tried to create a replacement for the function glutFullScreen()
which would detect an existing vroot window and somehow "attach" the
graphics to this window, instead of just creating a completely new
window.
I've been able to detect the presences of a VROOT window, but I have
not yet been able to get GLUT to use it.
The problems might be due to inherent protections between several
users modifying the same window, or it could be as simple as not
correctly setting up the GL context.
OpenGL screensaver 'hacks' from xlock 'modules'
Most of the xscreensaver graphical hacks, about 130 of them, are
written in pure X11 graphics, but about 60 of them are written in
OpenGL.
The code for all the hacks is found in the hacks
subdirectory, while the OpenGL hacks are found under this in
hacks/glx (since they use glX to open windows and read input
and window events).
These are yet another example of a clever bit of interface code making
it possible to use a large existing base of graphics code.
Most of the glX hacks are actually from a competing screensaver
program, called xlockmore, which is the successor to another
screen locking program, called
xlock.
The structure of xlockmore is slightly different from xscreensaver.
Each separate graphics demo is a 'module', and they all are compiled
together into one monolithic program.
Jamie Zawinski, the author of xscreensaver, wrote a bit of interface
code which allows the xlockmore 'modules' to be compiled as standlone
graphical 'hacks' for xscreensaver.
This might be considered a kludge, but it's a very useful and clever
kludge.
OpenGL for BOINC without GLUT
In the event that we decide to stop using GLUT for BOINC graphics on
Linux then we will have to write our own replacement code.
This code will have to find the VROOT window (if such exists,
otherwise create a fullscreen window), create an X11 "Visual" to go
with it, create a GL graphical "context", and then run an event loop
which renders a single frame of graphics and then processes input
events or window events.
This is already done for BOINC in Windows
(see the file
windows_opengl.C), so emulating that file would be helpful.
OpenGL for BOINC with freeglut
An alternative to GLUT is freeglut...
starboard - using the GL 'hacks' with BOINC
As already demonstrated above, there is a long tradition in the field
of X11 screensavers of writing a layer of interface code which
enables one to use a wide variety of pre-existing graphics routines in
a new way.
Following this tradition, I propose to write a layer of interface code
which will allow any of the glX graphics hacks from xscreensaver to be
used as screensaver graphics threads in BOINC applications.
An additional complication is that BOINC is written in C++, while
screensaver is in strict ANSI C.
Copyright ©
2010
by Spy Hill Research
http://www.Spy-Hill.net/~myers/help/boinc/unix-screensaver.html
(served by Islay.spy-hill.com)
Last modified:
16 March 2010