eec6de53086277bb6874c77675e5b17755a9bb5d
[free-sw/xcb/demo] / tests / julia.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #include <xcb/xcb.h>
8 #include <xcb/shm.h>
9 #include <xcb/xcb_aux.h>
10 #include <xcb/xcb_image.h>
11 #define XCB_ALL_PLANES ~0
12
13 /* Needed for xcb_set_wm_protocols() */
14 #include <xcb/xcb_icccm.h>
15
16 #include "julia.h"
17
18 #define W_W 640
19 #define W_H 480
20
21 /* Parameters of the fractal */
22
23 /* double cr = -0.7927; */
24 /* double ci = 0.1609; */
25
26 /* double cr = 0.32; */
27 /* double ci = 0.043; */
28
29 /* double cr = -1.1380; */
30 /* double ci = -0.2403; */
31
32 /* double cr = -0.0986; */
33 /* double ci = -0.65186; */
34
35 /* double cr = -0.1225; */
36 /* double ci = 0.7449; */
37
38 double cr = -0.3380;
39 double ci = -0.6230;
40 double origin_x = -1.8;
41 double origin_y = -1.2;
42 double width = 3.6;
43 double height = 2.4;
44
45 /* Numbers of colors in the palette */
46 int cmax = 316;
47
48 static xcb_atom_t
49 get_atom (xcb_connection_t *connection, const char *atomName)
50 {
51   if (atomName == NULL)
52     return XCB_NONE;
53   xcb_atom_t atom = XCB_NONE;
54   xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection,
55         xcb_intern_atom(connection, 0, strlen(atomName), atomName), NULL);
56   if (reply)
57     {
58       atom = reply->atom;
59       free(reply);
60     }
61   return atom;
62 }
63
64 void
65 palette_julia (Data *datap)
66 {
67   xcb_alloc_color_reply_t *rep;
68   int               i;
69
70   datap->palette = (uint32_t *)malloc (sizeof (uint32_t) * cmax);
71   
72   for (i = 0 ; i < cmax ; i++)
73     {
74       if (i < 128)
75         rep = xcb_alloc_color_reply (datap->conn,
76                                   xcb_alloc_color (datap->conn,
77                                                  datap->cmap,
78                                                  i<<9, 0, 0),
79                                   0);
80       else if (i < 255)
81         rep = xcb_alloc_color_reply (datap->conn,
82                                   xcb_alloc_color (datap->conn,
83                                                  datap->cmap,
84                                                  65535, (i-127)<<9, 0),
85                                   0);
86       else
87         rep = xcb_alloc_color_reply (datap->conn,
88                                   xcb_alloc_color (datap->conn,
89                                                  datap->cmap,
90                                                  65535, 65535, (i-255)<<10),
91                                   0);
92       
93       if (!rep)
94         datap->palette[i] = 0;
95       else
96         datap->palette[i] = rep->pixel;
97       free (rep);
98     }
99   
100 }
101
102 void
103 draw_julia (Data *datap)
104 {
105   double    zr, zi, t;
106   int       c;
107   int       i, j;
108   
109   datap->image = xcb_image_get (datap->conn, datap->draw,
110                        0, 0, W_W, W_H,
111                        XCB_ALL_PLANES, datap->format);
112   
113   assert(datap->image);
114
115   for (i = 0 ; i < datap->image->width ; i++)
116     for (j = 0 ; j < datap->image->height ; j++)
117       {
118         zr = origin_x + width * (double)i / (double)datap->image->width;
119         zi = origin_y + height * (double)j / (double)datap->image->height;
120         c = 0;
121         while ((zr*zr + zi*zi < 4.0) &&
122                (c < cmax-1))
123           {
124             t = zr;
125             zr = zr*zr - zi*zi + cr;
126             zi = 2.0*t*zi + ci;
127             c++;
128           }
129         xcb_image_put_pixel (datap->image,
130                           i,j,
131                           datap->palette[c]);
132       }
133
134   xcb_image_put (datap->conn, datap->draw, datap->gc, datap->image,
135                0, 0, 0);
136 }
137
138 int
139 main (int argc, char *argv[])
140 {
141   Data             data;
142   xcb_screen_t       *screen;
143   xcb_drawable_t      win;
144   xcb_drawable_t      rect;
145   xcb_gcontext_t      bgcolor;
146   uint32_t           mask;
147   uint32_t           valgc[2];
148   uint32_t           valwin[3];
149   xcb_rectangle_t     rect_coord = { 0, 0, W_W, W_H};
150   int              screen_num;
151   
152   data.conn = xcb_connect (0, &screen_num);
153   screen = xcb_aux_get_screen (data.conn, screen_num);
154   data.depth = xcb_aux_get_depth (data.conn, screen);
155
156   win = screen->root;
157
158   data.gc = xcb_generate_id (data.conn);
159   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
160   valgc[0] = screen->black_pixel;
161   valgc[1] = 0; /* no graphics exposures */
162   xcb_create_gc (data.conn, data.gc, win, mask, valgc);
163
164   bgcolor = xcb_generate_id (data.conn);
165   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
166   valgc[0] = screen->white_pixel;
167   valgc[1] = 0; /* no graphics exposures */
168   xcb_create_gc (data.conn, bgcolor, win, mask, valgc);
169
170   data.draw = xcb_generate_id (data.conn);
171   mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
172   valwin[0] = screen->white_pixel;
173   valwin[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE;
174   valwin[2] = XCB_EVENT_MASK_BUTTON_PRESS;
175   xcb_create_window (data.conn, 0,
176                    data.draw,
177                    screen->root,
178                    0, 0, W_W, W_H,
179                    10,
180                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
181                    screen->root_visual,
182                    mask, valwin);
183   xcb_map_window (data.conn, data.draw);
184
185   rect = xcb_generate_id (data.conn);
186   xcb_create_pixmap (data.conn, data.depth,
187                    rect, data.draw,
188                    W_W, W_H);
189   xcb_poly_fill_rectangle(data.conn, rect, bgcolor, 1, &rect_coord);
190
191   xcb_map_window (data.conn, data.draw);
192
193   data.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
194
195   data.cmap = xcb_generate_id (data.conn);
196   xcb_create_colormap (data.conn,
197                      XCB_COLORMAP_ALLOC_NONE,
198                      data.cmap,
199                      data.draw,
200                      screen->root_visual);
201
202   palette_julia (&data);
203
204   xcb_atom_t deleteWindowAtom = get_atom(data.conn, "WM_DELETE_WINDOW");
205   /* Listen to X client messages in order to be able to pickup
206      the "delete window" message that is generated for example
207      when someone clicks the top-right X button within the window
208      manager decoration (or when user hits ALT-F4). */
209   xcb_set_wm_protocols (data.conn, data.draw, 1, &deleteWindowAtom);
210
211   xcb_flush (data.conn); 
212
213   bool finished = false;
214   while (!finished)
215     {
216       xcb_generic_event_t *e;
217       if (e = xcb_wait_for_event(data.conn))
218         {
219           switch (e->response_type & 0x7f)
220             {
221             case XCB_EXPOSE:
222               {
223                 xcb_copy_area(data.conn, rect, data.draw, bgcolor,
224                                 0, 0, 0, 0, W_W, W_H);
225                 draw_julia (&data);
226                 xcb_flush (data.conn);
227                 break;
228               }
229             case XCB_CLIENT_MESSAGE:
230               {
231                 if (((xcb_client_message_event_t *)e)->data.data32[0] == deleteWindowAtom)
232                   {
233                     finished = true;
234                   }
235                 break;
236               }
237             case XCB_BUTTON_PRESS:
238               {
239                 finished = true;
240                 break;
241               }
242           }
243         free (e);
244       }
245     }
246
247   if (data.palette)
248     free (data.palette);
249   if (data.image)
250     xcb_image_destroy (data.image);
251   xcb_disconnect (data.conn);
252
253   return 0;
254 }