make flames/julia/neko demos use XCB_EVENT_RESPONSE_TYPE to determine event type
[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 <xcb/xcb.h>
12 #include <xcb/shm.h>
13 #include <xcb/xcb_aux.h>
14 #include <xcb/xcb_image.h>
15 #define XCB_ALL_PLANES ~0
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 xcb_shm_segment_info_t 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 = xcb_image_shm_get (datap->conn, datap->draw,
54                           datap->image, shminfo,
55                           0, 0,
56                           XCB_ALL_PLANES);
57       assert(i);
58     }
59   else
60     {
61       datap->image = xcb_image_get (datap->conn, datap->draw,
62                                   0, 0, W_W, W_H,
63                                   XCB_ALL_PLANES, 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         xcb_image_put_pixel (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         xcb_image_put_pixel (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     xcb_image_shm_put (datap->conn, datap->draw, datap->gc,
98                     datap->image, shminfo,
99                     0, 0, 0, 0, W_W, W_H, 0);
100   else
101     {
102       xcb_image_put (datap->conn, datap->draw, datap->gc, datap->image,
103                    0, 0, 0);
104       xcb_image_destroy (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 <= 2.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       xcb_disconnect (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   xcb_shm_query_version_reply_t *rep;
133
134   rep = xcb_shm_query_version_reply (datap->conn,
135                                  xcb_shm_query_version (datap->conn),
136                                  NULL);
137   if (rep)
138     {
139       uint8_t 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 = xcb_image_create_native (datap->conn, W_W, W_H,
148                                         format, datap->depth, NULL, ~0, NULL);
149       assert(datap->image);
150
151       shminfo.shmid = shmget (IPC_PRIVATE,
152                               datap->image->stride*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 = xcb_generate_id (datap->conn);
160       xcb_shm_attach (datap->conn, shminfo.shmseg,
161                     shminfo.shmid, 0);
162       shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0);
163       assert(shmctl_status != -1);
164       free (rep);
165     }
166
167   if (datap->image)
168     {
169       printf ("Use of shm.\n");
170       do_shm = 1;
171     }
172   else
173     {
174       printf ("Can't use shm. Use standard functions.\n");
175       shmdt (shminfo.shmaddr);                 
176       shmctl (shminfo.shmid, IPC_RMID, 0);
177       datap->image = NULL;
178     }
179 }
180
181 int
182 main (int argc, char *argv[])
183 {
184   Data             data;
185   xcb_screen_t       *screen;
186   xcb_drawable_t      win;
187   xcb_drawable_t      rect;
188   xcb_gcontext_t      bgcolor;
189   uint32_t           mask;
190   uint32_t           valgc[2];
191   uint32_t           valwin[3];
192   xcb_rectangle_t     rect_coord = { 0, 0, W_W, W_H};
193   xcb_generic_event_t *e;
194   int              try_shm;
195   int              screen_num;
196   int              i;
197   
198   try_shm = 0;
199
200   /* Arguments test */
201   if (argc < 2)
202     {
203       printf ("Usage: lissajoux try_shm\n");
204       printf ("         try_shm == 0: shm not used\n");
205       printf ("         try_shm != 0: shm is used (if available)\n");
206       exit (0);
207     }
208   if (argc >= 2)
209     try_shm = atoi (argv[1]);
210   if (try_shm != 0)
211     try_shm = 1;
212
213   data.conn = xcb_connect (0, &screen_num);
214   screen = xcb_aux_get_screen(data.conn, screen_num);
215   data.depth = xcb_aux_get_depth (data.conn, screen);
216
217   win = screen->root;
218
219   data.gc = xcb_generate_id (data.conn);
220   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
221   valgc[0] = screen->black_pixel;
222   valgc[1] = 0; /* no graphics exposures */
223   xcb_create_gc (data.conn, data.gc, win, mask, valgc);
224
225   bgcolor = xcb_generate_id (data.conn);
226   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
227   valgc[0] = screen->white_pixel;
228   valgc[1] = 0; /* no graphics exposures */
229   xcb_create_gc (data.conn, bgcolor, win, mask, valgc);
230
231   data.draw = xcb_generate_id (data.conn);
232   mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
233   valwin[0] = screen->white_pixel;
234   valwin[1] = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE;
235   valwin[2] = XCB_EVENT_MASK_BUTTON_PRESS;
236   xcb_create_window (data.conn, 0,
237                    data.draw,
238                    screen->root,
239                    0, 0, W_W, W_H,
240                    10,
241                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
242                    screen->root_visual,
243                    mask, valwin);
244   xcb_map_window (data.conn, data.draw);
245
246   rect = xcb_generate_id (data.conn);
247   xcb_create_pixmap (data.conn, data.depth,
248                    rect, data.draw,
249                    W_W, W_H);
250   xcb_poly_fill_rectangle(data.conn, rect, bgcolor, 1, &rect_coord);
251
252   data.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
253   xcb_flush (data.conn); 
254
255   if (try_shm)
256     shm_test (&data);
257
258   for (i = 0; i < 3600; i++) {
259     tab_cos[i] = cos (2.0 * 3.1415926535897 * (double)i / 3600.0);
260     tab_sin[i] = sin (2.0 * 3.1415926535897 * (double)i / 3600.0);
261   }
262
263   time_start = get_time ();
264   t_previous = 0.0;
265   while (1)
266     {
267       e = xcb_poll_for_event(data.conn);
268       if (e)
269         {
270           switch (e->response_type)
271             {
272             case XCB_EXPOSE:
273               xcb_copy_area(data.conn, rect, data.draw, bgcolor,
274                           0, 0, 0, 0, W_W, W_H);
275               break;
276             }
277           free (e);
278         }
279       step (&data);
280       xcb_flush (data.conn);
281       t_previous = t;
282     }
283   /*NOTREACHED*/
284 }