9be7b88d697d780a58af705553dd3d897dec66ed
[xscreensaver] / README.hacking
1
2 ==========================================================================
3
4                      Writing new XScreenSaver modules
5
6 ==========================================================================
7
8
9 Generally, the best way to learn how to do something is to find a similar
10 program, and play around with it until you understand it.  Another
11 approach is to not worry about understanding it, but to just hack it out.
12 Either way, your best bet is probably to start with one of the existing
13 xscreensaver demos, included in the "hacks/" directory, rename the file,
14 and edit it until it does what you want.
15
16 The "Greynetic" and "Deluxe" hacks are probably good ones to start with,
17 since they are so very simple.  For GL programs, "DangerBall" is a good
18 example.
19
20
21 ==========================================================================
22 Requirements for inclusion with the XScreenSaver collection
23 ==========================================================================
24
25   If you come up with anything, send it to me!  If it's good, I'd love to
26   include it in the xscreensaver distribution.  However, there are a few
27   requirements for me to distribute it:
28
29   - Write in portable ANSI C.  No C++.  No nonstandard libraries.
30
31   - Write a .man page describing all command-line options.
32
33   - Write an .xml file describing the graphical configuration dialog box.
34
35   - Include a BSD-like copyright/license notice at the top of each source
36     file (preferably, just use the one from "screenhack.h", and include
37     your name and the current year).  The GNU GPL is not compatible with
38     the rest of XScreenSaver.
39
40
41 ==========================================================================
42 The XScreenSaver API
43 ==========================================================================
44
45   - Start with #include "screenhack.h"
46
47   - Define 2 global variables:
48
49       yoursavername_defaults -- Default values for the resources you use.
50       yoursavername_options  -- The command-line options you accept.
51
52   - Define 5 functions:
53
54       yoursavername_init     -- Return an object holding your global state.
55       yoursavername_draw     -- Draw a single frame, quickly.
56       yoursavername_free     -- Free everything you've allocated.
57       yoursavername_reshape  -- Called when the window is resized.
58       yoursavername_event    -- Called when a keyboard or mouse event happens.
59
60       The "event" function will only be called when running in a window
61       (not as a screen saver).  The "reshape" event will be called when the
62       window size changes, or (as a screen saver) when the display size
63       changes as a result of a RANDR event (e.g., plugging in a new monitor).
64
65       It's ok for both the "event" and "resize" functions to do nothing.
66
67   - All other functions should be static.
68
69   - The last line of the file should be 
70     XSCREENSAVER_MODULE ("YourSaverName", yoursavername)
71
72   - Finally, edit the Makefile to add a rule for your program.
73     Just cut-and-paste one of the existing rules.
74
75   Your "draw" must not run for more than a fraction of a second without
76   returning.  This means "don't call usleep()".  Everything has to be a
77   state machine.
78
79   You may not store global state in global variables, or in function-local
80   static variables.  All of your runtime state must be encapsulted in the
81   "state" object created by your "init" function.  If you use global or
82   static variables, your screen saver will not work properly on MacOS.
83
84   Do not call XSync() or XFlush().  If you think you need to do that, it
85   probably means that you are you are relying on the speed of the graphics
86   card for timing, which probably means that your "draw" function is
87   taking too long.
88
89
90 ==========================================================================
91 The XLockMore API
92 ==========================================================================
93
94   Some of the display modes that come with xscreensaver were ported from
95   XLock, and so, for historical reasons, they follow a slightly different
96   programming convention.  For newly-written Xlib programs, you'd be
97   better off following the pattern used in hacks like "Deluxe" than in
98   hacks like "Flag".  The XLockMore ones are the ones that begin with
99   "#ifdef STANDALONE" and #include "xlockmore.h".
100
101   But, all OpenGL screen savers have to follow the XLockMore API.
102
103   The XLockMore API is similar to the XScreenSaver API, in that you define
104   (roughly) the same set of functions, but the naming conventions are
105   slightly different.  Instead of "hackname_init", it's "init_hackname",
106   and it should be preceeded with the pseudo-declaration ENTRYPOINT.
107
108   One annoying mis-feature of the XLockMore API is that it *requires* you
109   to make use of global variables for two things: first, for each of your
110   command line options; and second, for an array that holds your global
111   state objects.  These are the only exceptions to the "never use global
112   variables" rule.
113
114
115 ==========================================================================
116 Programming Tips
117 ==========================================================================  
118
119   - Your screen saver should look reasonable at 20-30 frames per second.
120     That is, do not assume that your "draw" function will be called more
121     than 20 times a second.  Even if you return a smaller requested delay
122     than that, you might not get it.  Likewise, if your "draw" function
123     takes longer than 1/20th of a second to run, your screen saver may be
124     consuming too much CPU.
125
126   - Don't make assumptions about the depth of the display, or whether it
127     is colormapped.  You must allocate all your colors explicitly: do not
128     assume you can construct an RGB value and use that as a pixel value
129     directly.  Use the utility routines provided by "utils/colors.h" to
130     simplify color allocation.
131
132   - It is better to eliminate flicker by double-buffering to a Pixmap
133     than by erasing and re-drawing objects.  Do not use drawing tricks
134     involving XOR.
135
136   - If you use double-buffering, have a resource to turn it off. (MacOS
137     has double-buffering built in, so you'd be triple-buffering.)
138
139   - Understand the differences between Pixmaps and XImages, and keep in
140     mind which operations are happening in client memory and which are in
141     server memory, and which cause latency due to server round-trips.
142     Sometimes using the Shared Memory extension can be helpful, but
143     probably not as often as you might think.
144
145   - On modern machines, OpenGL will always run faster than Xlib.  It's
146     also more portable.  Consider writing in OpenGL whenever possible.
147
148
149 ==========================================================================
150 The MacOS X Port
151 ==========================================================================
152
153   Though XScreenSaver started its life as an X11 program, it also now runs
154   on MacOS X.  If you do your development on an X11 system, and follow the
155   usual XScreenSaver APIs, you shouldn't need to do anything special for
156   it to also work on MacOS.
157
158   The preprocessor macro HAVE_COCOA will be defined when being compiled in
159   a MacOS (Cocoa/Quartz) environment, and will be undefined when compiling
160   against "real" Xlib.
161
162   To compile on MacOS, use the XCode project included in the source
163   distribution.  You shouldn't need to have X11 installed, and shouldn't
164   need to run "configure" first.  MacOS 10.4.0 and XCode 3.1 or newer are
165   required.
166
167 ==========================================================================