tizen 2.4 release
[framework/uifw/elementary.git] / src / examples / efl_thread_6.c
1 //Compile with:
2 //gcc -o efl_thread_6 efl_thread_6.c -g `pkg-config --cflags --libs elementary`
3 #include <Elementary.h>
4
5 static Evas_Object *win = NULL;
6 static Eina_List *threads;
7
8 struct info
9 {
10    Evas_Object *obj;
11    int *pix;
12 };
13
14 // BEGIN - code running in my custom thread instance
15 //
16 static void
17 mandel(Ecore_Thread *th, int *pix, int w, int h)
18 {
19    double x, xx, y, cx, cy, cox, coy;
20    int iteration, hx, hy, val, r, g, b, rr, gg, bb;
21    int itermax = 10000;
22    double magnify = 0.02;
23
24    // this mandel calc is run in the worker threads so it's here. it is
25    // just here to calculate something and consume cpu to demonstrate the
26    // ecore thread worker queue. don't pay much attention to the below code
27    magnify += ((double)(rand() % 100) / 100.0) / 4.0;
28    cox = (double)(rand() % 100) / 100.0;
29    coy = (double)(rand() % 100) / 100.0;
30    cox /= (magnify * 3.0);
31    r = rand() % 255; g = rand() % 255; b = rand() % 255;
32    for (hy = 0; hy < h; hy++)
33      {
34         // every line check if thread has been cancelled to return early
35         if (ecore_thread_check(th)) return;
36         for (hx = 0; hx < w; hx++)
37           {
38              cx = (((float)hx) / ((float)w) - 0.5) / (magnify * 3.0);
39              cy = (((float)hy) / ((float)h) - 0.5) / (magnify * 3.0);
40              cx += cox;
41              cy += coy;
42              x = 0.0;
43              y = 0.0;
44              for (iteration = 1; iteration < itermax; iteration++)
45                {
46                   xx = (x * x) - (y * y) + cx;
47                   y = (2.0 * x * y) + cy;
48                   x = xx;
49                   if (((x * x) + (y * y)) > 100.0) iteration = 999999;
50                }
51              val = (((x * x) + (y * y)) * 2.55) / 100.0;
52              if (val > 255) val = 255;
53              if (iteration >= 99999)
54                {
55                   rr = (r * val) / 255;
56                   gg = (g * val) / 255;
57                   bb = (b * val) / 255;
58                   pix[(hy * w) + hx] =
59                      (val  << 24) | (rr << 16) | (gg << 8) | (bb);
60                }
61              else
62                pix[(hy * w) + hx] = 0xffffffff;
63           }
64      }
65 }
66
67 static void
68 th_do(void *data, Ecore_Thread *th)
69 {
70    struct info *inf = data;
71    // CANNOT TOUCH inf->obj here! just inf->pix which is 256x256 @ 32bpp
72    // quick and dirty to consume some cpu - do a mandelbrot calc
73    mandel(th, inf->pix, 256, 256);
74 }
75 //
76 // END - code running in my custom thread instance
77
78 static void // thread job finished - collect results and put in img obj
79 th_end(void *data, Ecore_Thread *th)
80 {
81    struct info *inf = data;
82
83    // copy data to object, free calculated data and info struc
84    evas_object_image_data_copy_set(inf->obj, inf->pix);
85    evas_object_show(inf->obj);
86    free(inf->pix);
87    free(inf);
88    threads = eina_list_remove(threads, th);
89 }
90
91 static void // if the thread is cancelled - free pix, keep obj tho
92 th_cancel(void *data, Ecore_Thread *th)
93 {
94    struct info *inf = data;
95
96    // just free pixel data and info struct
97    free(inf->pix);
98    free(inf);
99 }
100
101 static Eina_Bool // animate the objects so you see all the madels move
102 anim(void *data)
103 {
104    Evas_Object *o = data;
105    double t, z;
106    int w, h, v;
107    Evas_Coord x, y;
108
109    // just calculate some position using the pointer value of the object as
110    // a seed value to make different objects go into different places over time
111    v = ((int)(uintptr_t)o) & 0xff;
112    t = ecore_loop_time_get();
113    w = 100 + ((v * 100) >> 8);
114    h = 100 + ((v * 100) >> 8);
115    z = (double)(v) / 100.0;
116    x = (w * sin(t));
117    y = (h * cos(t + z));
118    // do the actual move
119    evas_object_move(o, 200 + x - 128, 200 + y - 128);
120    // keep looping - return true
121    return EINA_TRUE;
122 }
123
124 EAPI_MAIN int
125 elm_main(int argc, char **argv)
126 {
127    Evas_Object *o;
128    Ecore_Thread *th;
129    int i;
130
131    elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
132
133    win = elm_win_util_standard_add("efl-thread-6", "EFL Thread 6");
134    elm_win_autodel_set(win, EINA_TRUE);
135
136    // queue up 64 mandel generation thread jobs
137    for (i = 0; i < 64; i++)
138      {
139         struct info *inf;
140
141         // create ecore thread to do some threaded job inside the worker pool
142         inf = malloc(sizeof(struct info));
143         if (inf)
144           {
145              o = evas_object_image_filled_add(evas_object_evas_get(win));
146              evas_object_image_size_set(o, 256, 256);
147              evas_object_image_alpha_set(o, EINA_TRUE);
148              evas_object_resize(o, 256, 256);
149              inf->obj = o;
150              inf->pix = malloc(256 * 256 * sizeof(int));
151              th = ecore_thread_run(th_do, th_end, th_cancel, inf);
152              threads = eina_list_append(threads, th);
153              // bonus - slide the objects around all the time with an
154              // animator that ticks off every frame.
155              ecore_animator_add(anim, o);
156           }
157      }
158
159    evas_object_resize(win, 400, 400);
160    evas_object_show(win);
161
162    elm_run();
163
164    // if some threads are still running - cancel them
165    EINA_LIST_FREE(threads, th) ecore_thread_cancel(th);
166
167
168    return 0;
169 }
170 ELM_MAIN()