Move .cvsignore to .gitignore.
[free-sw/xcb/demo] / tests / lissajoux.c
1 #include <assert.h>
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <math.h>
6 #include <sys/time.h>
7
8 #include <sys/ipc.h>
9 #include <sys/shm.h>
10
11 #include <X11/Xlib.h>
12 #include <X11/XCB/xcb.h>
13 #include <X11/XCB/shm.h>
14 #include <X11/XCB/xcb_aux.h>
15 #include <X11/XCB/xcb_image.h>
16
17 #include "lissajoux.h"
18
19 #define W_W 100
20 #define W_H 100
21
22 double time_start;
23 int    loop_count;
24 double t_previous;
25 double t;
26 int    do_shm = 0;
27
28 XCBShmSegmentInfo shminfo;
29
30 double
31 get_time(void)
32 {
33   struct timeval timev;
34   
35   gettimeofday(&timev, NULL);
36
37   return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
38 }
39
40 void
41 draw_lissajoux (Data *datap)
42 {
43   int       i, nbr;
44   double    a1, a2, p1, p2;
45   double    pi, period;
46   double    x, y;
47   
48   if (do_shm)
49     { 
50       i = XCBImageSHMGet (datap->conn, datap->draw,
51                           datap->image, shminfo,
52                           0, 0,
53                           AllPlanes);
54       assert(i);
55     }
56   else
57     {
58       datap->image = XCBImageGet (datap->conn, datap->draw,
59                                   0, 0, W_W, W_H,
60                                   AllPlanes, datap->format);
61       assert(datap->image);
62     }
63   
64   pi = 3.1415926535897;
65   period = 2.0 * pi;
66   a1 = 2.0;
67   a2 = 3.0;
68   p1 = 4.0*t_previous*pi*0.05;
69   p2 = 0.0;
70
71   nbr = 1000;
72   for (i = 0 ; i < nbr ; i++)
73       {
74         x = cos (a1*i*period/nbr + p1);
75         y = sin (a2*i*period/nbr + p2);
76         XCBImagePutPixel (datap->image,
77                           (int)((double)(W_W-5)*(x+1)/2.0),
78                           (int)((double)(W_H-5)*(y+1)/2.0), 65535);
79       }
80
81   p1 = 4.0*t*pi*0.05;
82   p2 = 0.0;
83
84   for (i = 0 ; i < nbr ; i++)
85       {
86         x = cos (a1*i*period/nbr + p1);
87         y = sin (a2*i*period/nbr + p2);
88         XCBImagePutPixel (datap->image,
89                           (int)((double)(W_W-5)*(x+1)/2.0),
90                           (int)((double)(W_H-5)*(y+1)/2.0), 0);
91       }
92
93   if (do_shm)
94     XCBImageSHMPut (datap->conn, datap->draw, datap->gc,
95                     datap->image, shminfo,
96                     0, 0, 0, 0, W_W, W_H, 0);
97   else
98     {
99       XCBImagePut (datap->conn, datap->draw, datap->gc, datap->image,
100                    0, 0, 0, 0, W_W, W_H);
101       XCBImageDestroy (datap->image);
102     }
103 }
104
105 void
106 step (Data *datap)
107 {
108   loop_count++;
109   t = get_time () - time_start;
110
111   if (t <= 20.0)
112     {
113       draw_lissajoux (datap);
114     }
115   else
116     {
117       printf("FRAME COUNT..: %i frames\n", loop_count);
118       printf("TIME.........: %3.3f seconds\n", t);
119       printf("AVERAGE FPS..: %3.3f fps\n", (double)loop_count / t);
120       XCBDisconnect (datap->conn);
121       exit(0);
122     }
123 }
124
125 /* Return 0 if shm is not availaible, 1 otherwise */
126 void
127 shm_test (Data *datap)
128 {
129   XCBShmQueryVersionRep *rep;
130
131   rep = XCBShmQueryVersionReply (datap->conn,
132                                  XCBShmQueryVersion (datap->conn),
133                                  NULL);
134   if (rep)
135     {
136       CARD8 format;
137       int shmctl_status;
138       
139       if (rep->shared_pixmaps && 
140           (rep->major_version > 1 || rep->minor_version > 0))
141         format = rep->pixmap_format;
142       else
143         format = 0;
144       datap->image = XCBImageSHMCreate (datap->conn, datap->depth,
145                                       format, NULL, W_W, W_H);
146       assert(datap->image);
147
148       shminfo.shmid = shmget (IPC_PRIVATE,
149                               datap->image->bytes_per_line*datap->image->height,
150                               IPC_CREAT | 0777);
151       assert(shminfo.shmid != -1);
152       shminfo.shmaddr = shmat (shminfo.shmid, 0, 0);
153       assert(shminfo.shmaddr);
154       datap->image->data = shminfo.shmaddr;
155
156       shminfo.shmseg = XCBShmSEGNew (datap->conn);
157       XCBShmAttach (datap->conn, shminfo.shmseg,
158                     shminfo.shmid, 0);
159       shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0);
160       assert(shmctl_status != -1);
161     }
162
163   if (datap->image)
164     {
165       printf ("Use of shm.\n");
166       do_shm = 1;
167     }
168   else
169     {
170       printf ("Can't use shm. Use standard functions.\n");
171       shmdt (shminfo.shmaddr);                 
172       shmctl (shminfo.shmid, IPC_RMID, 0);
173       datap->image = NULL;
174     }
175 }
176
177 int
178 main (int argc, char *argv[])
179 {
180   Data             data;
181   XCBSCREEN       *screen;
182   XCBDRAWABLE      win;
183   XCBDRAWABLE      rect;
184   XCBGCONTEXT      bgcolor;
185   CARD32           mask;
186   CARD32           valgc[2];
187   CARD32           valwin[3];
188   XCBRECTANGLE     rect_coord = { 0, 0, W_W, W_H};
189   XCBGenericEvent *e;
190   int              try_shm;
191   int              screen_num;
192   
193   try_shm = 0;
194
195   /* Arguments test */
196   if (argc < 2)
197     {
198       printf ("Usage: lissajoux try_shm\n");
199       printf ("         try_shm == 0: shm not used\n");
200       printf ("         try_shm != 0: shm is used (if availaible)\n");
201       exit (0);
202     }
203   if (argc >= 2)
204     try_shm = atoi (argv[1]);
205   if (try_shm != 0)
206     try_shm = 1;
207
208   data.conn = XCBConnect (0, &screen_num);
209   screen = XCBAuxGetScreen(data.conn, screen_num);
210   data.depth = XCBAuxGetDepth (data.conn, screen);
211
212   win.window = screen->root;
213
214   data.gc = XCBGCONTEXTNew (data.conn);
215   mask = GCForeground | GCGraphicsExposures;
216   valgc[0] = screen->black_pixel;
217   valgc[1] = 0; /* no graphics exposures */
218   XCBCreateGC (data.conn, data.gc, win, mask, valgc);
219
220   bgcolor = XCBGCONTEXTNew (data.conn);
221   mask = GCForeground | GCGraphicsExposures;
222   valgc[0] = screen->white_pixel;
223   valgc[1] = 0; /* no graphics exposures */
224   XCBCreateGC (data.conn, bgcolor, win, mask, valgc);
225
226   data.draw.window = XCBWINDOWNew (data.conn);
227   mask = XCBCWBackPixel | XCBCWEventMask | XCBCWDontPropagate;
228   valwin[0] = screen->white_pixel;
229   valwin[1] = KeyPressMask | ButtonReleaseMask | ExposureMask;
230   valwin[2] = ButtonPressMask;
231   XCBCreateWindow (data.conn, 0,
232                    data.draw.window,
233                    screen->root,
234                    0, 0, W_W, W_H,
235                    10,
236                    InputOutput,
237                    screen->root_visual,
238                    mask, valwin);
239   XCBMapWindow (data.conn, data.draw.window);
240
241   rect.pixmap = XCBPIXMAPNew (data.conn);
242   XCBCreatePixmap (data.conn, data.depth,
243                    rect.pixmap, data.draw,
244                    W_W, W_H);
245   XCBPolyFillRectangle(data.conn, rect, bgcolor, 1, &rect_coord);
246
247   data.format = ZPixmap;
248   XCBSync (data.conn, 0); 
249
250   if (try_shm)
251     shm_test (&data);
252
253   time_start = get_time ();
254   t_previous = 0.0;
255   while (1)
256     {
257       e = XCBPollForEvent(data.conn, NULL);
258       if (e)
259         {
260           switch (e->response_type)
261             {
262             case XCBExpose:
263               XCBCopyArea(data.conn, rect, data.draw, bgcolor,
264                           0, 0, 0, 0, W_W, W_H);
265               XCBSync (data.conn, 0);
266               break;
267             }
268           free (e);
269         }
270       step (&data);
271       XCBFlush (data.conn);
272       t_previous = t;
273     }
274   /*NOTREACHED*/
275 }