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