Merge branch 'master' of git+ssh://iano@git.freedesktop.org/git/xcb
[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       XCBDisconnect (datap->conn);
124       exit(0);
125     }
126 }
127
128 /* Return 0 if shm is not available, 1 otherwise */
129 void
130 shm_test (Data *datap)
131 {
132   XCBShmQueryVersionRep *rep;
133
134   rep = XCBShmQueryVersionReply (datap->conn,
135                                  XCBShmQueryVersion (datap->conn),
136                                  NULL);
137   if (rep)
138     {
139       CARD8 format;
140       int shmctl_status;
141       
142       if (rep->shared_pixmaps && 
143           (rep->major_version > 1 || rep->minor_version > 0))
144         format = rep->pixmap_format;
145       else
146         format = 0;
147       datap->image = XCBImageSHMCreate (datap->conn, datap->depth,
148                                       format, NULL, W_W, W_H);
149       assert(datap->image);
150
151       shminfo.shmid = shmget (IPC_PRIVATE,
152                               datap->image->bytes_per_line*datap->image->height,
153                               IPC_CREAT | 0777);
154       assert(shminfo.shmid != -1);
155       shminfo.shmaddr = shmat (shminfo.shmid, 0, 0);
156       assert(shminfo.shmaddr);
157       datap->image->data = shminfo.shmaddr;
158
159       shminfo.shmseg = XCBShmSEGNew (datap->conn);
160       XCBShmAttach (datap->conn, shminfo.shmseg,
161                     shminfo.shmid, 0);
162       shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0);
163       assert(shmctl_status != -1);
164     }
165
166   if (datap->image)
167     {
168       printf ("Use of shm.\n");
169       do_shm = 1;
170     }
171   else
172     {
173       printf ("Can't use shm. Use standard functions.\n");
174       shmdt (shminfo.shmaddr);                 
175       shmctl (shminfo.shmid, IPC_RMID, 0);
176       datap->image = NULL;
177     }
178 }
179
180 int
181 main (int argc, char *argv[])
182 {
183   Data             data;
184   XCBSCREEN       *screen;
185   XCBDRAWABLE      win;
186   XCBDRAWABLE      rect;
187   XCBGCONTEXT      bgcolor;
188   CARD32           mask;
189   CARD32           valgc[2];
190   CARD32           valwin[3];
191   XCBRECTANGLE     rect_coord = { 0, 0, W_W, W_H};
192   XCBGenericEvent *e;
193   int              try_shm;
194   int              screen_num;
195   int              i;
196   
197   try_shm = 0;
198
199   /* Arguments test */
200   if (argc < 2)
201     {
202       printf ("Usage: lissajoux try_shm\n");
203       printf ("         try_shm == 0: shm not used\n");
204       printf ("         try_shm != 0: shm is used (if available)\n");
205       exit (0);
206     }
207   if (argc >= 2)
208     try_shm = atoi (argv[1]);
209   if (try_shm != 0)
210     try_shm = 1;
211
212   data.conn = XCBConnect (0, &screen_num);
213   screen = XCBAuxGetScreen(data.conn, screen_num);
214   data.depth = XCBAuxGetDepth (data.conn, screen);
215
216   win.window = screen->root;
217
218   data.gc = XCBGCONTEXTNew (data.conn);
219   mask = GCForeground | GCGraphicsExposures;
220   valgc[0] = screen->black_pixel;
221   valgc[1] = 0; /* no graphics exposures */
222   XCBCreateGC (data.conn, data.gc, win, mask, valgc);
223
224   bgcolor = XCBGCONTEXTNew (data.conn);
225   mask = GCForeground | GCGraphicsExposures;
226   valgc[0] = screen->white_pixel;
227   valgc[1] = 0; /* no graphics exposures */
228   XCBCreateGC (data.conn, bgcolor, win, mask, valgc);
229
230   data.draw.window = XCBWINDOWNew (data.conn);
231   mask = XCBCWBackPixel | XCBCWEventMask | XCBCWDontPropagate;
232   valwin[0] = screen->white_pixel;
233   valwin[1] = KeyPressMask | ButtonReleaseMask | ExposureMask;
234   valwin[2] = ButtonPressMask;
235   XCBCreateWindow (data.conn, 0,
236                    data.draw.window,
237                    screen->root,
238                    0, 0, W_W, W_H,
239                    10,
240                    InputOutput,
241                    screen->root_visual,
242                    mask, valwin);
243   XCBMapWindow (data.conn, data.draw.window);
244
245   rect.pixmap = XCBPIXMAPNew (data.conn);
246   XCBCreatePixmap (data.conn, data.depth,
247                    rect.pixmap, data.draw,
248                    W_W, W_H);
249   XCBPolyFillRectangle(data.conn, rect, bgcolor, 1, &rect_coord);
250
251   data.format = ZPixmap;
252   XCBSync (data.conn, 0); 
253
254   if (try_shm)
255     shm_test (&data);
256
257   for (i = 0; i < 3600; i++) {
258     tab_cos[i] = cos (2.0 * 3.1415926535897 * (double)i / 3600.0);
259     tab_sin[i] = sin (2.0 * 3.1415926535897 * (double)i / 3600.0);
260   }
261
262   time_start = get_time ();
263   t_previous = 0.0;
264   while (1)
265     {
266       e = XCBPollForEvent(data.conn, NULL);
267       if (e)
268         {
269           switch (e->response_type)
270             {
271             case XCBExpose:
272               XCBCopyArea(data.conn, rect, data.draw, bgcolor,
273                           0, 0, 0, 0, W_W, W_H);
274               XCBSync (data.conn, 0);
275               break;
276             }
277           free (e);
278         }
279       step (&data);
280       XCBFlush (data.conn);
281       t_previous = t;
282     }
283   /*NOTREACHED*/
284 }