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