1 #include <stdio.h>
2 #include <Eina.h>
3 #include <Ecore.h>
4 #include <Ecore_Evas.h>
5 #include <Ecore_Buffer.h>
6 #include <Ecore_Buffer_Queue.h>
7 #include <Evas.h>
8 
9 #ifdef DEBUG
10 #define LOG(f, x...) printf("[PROVIDER|%30.30s|%04d] " f "\n", __func__, __LINE__, ##x)
11 #else
12 #define LOG(f, x...)
13 #endif
14 
15 typedef struct _Provider_Data
16 {
17    Ecore_Buffer_Provider *provider;
18    Ecore_Buffer *buffer;
19    Eina_List *buffer_list;
20    Ecore_Job *render_job;
21    Ecore_Idle_Enterer *post_render;
22    unsigned int w, h;
23 } Provider_Data;
24 
25 const char *name = "ecore_buffer_queue_test";
26 
27 static void _provider_render_queue(Provider_Data *pd);
28 
29 static void
shutdown_all(void)30 shutdown_all(void)
31 {
32    ecore_buffer_queue_shutdown();
33    ecore_buffer_shutdown();
34    ecore_evas_shutdown();
35    ecore_shutdown();
36    eina_shutdown();
37 }
38 
39 static Eina_Bool
init_all(void)40 init_all(void)
41 {
42    if (!eina_init()) goto err;
43    if (!ecore_init()) goto err;
44    if (!ecore_evas_init()) goto err;
45    if (!ecore_buffer_init()) goto err;
46    if (!ecore_buffer_queue_init()) goto err;
47 
48    return EINA_TRUE;
49 err:
50    shutdown_all();
51    return EINA_FALSE;
52 }
53 
54 Ecore_Buffer *
_provider_buffer_get(Provider_Data * pd,unsigned int w,unsigned int h,unsigned int format)55 _provider_buffer_get(Provider_Data *pd, unsigned int w, unsigned int h, unsigned int format)
56 {
57    Ecore_Buffer *buffer = NULL;
58    Ecore_Buffer_Return ret;
59    unsigned int res_w, res_h, res_format;
60 
61    LOG("Dequeue");
62    ret = ecore_buffer_provider_buffer_acquire(pd->provider, &buffer);
63 
64    if (ret == ECORE_BUFFER_RETURN_NEED_ALLOC)
65      {
66         buffer = ecore_buffer_new("shm", w, h, format, 0);
67         pd->buffer_list = eina_list_append(pd->buffer_list, buffer);
68         LOG("No buffer in Queue, Create Buffer");
69      }
70    else if (ret == ECORE_BUFFER_RETURN_SUCCESS)
71      {
72         ecore_buffer_size_get(buffer, &res_w, &res_h);
73         res_format = ecore_buffer_format_get(buffer);
74         if ((res_w != w) || (res_h != h) || (res_format != format))
75           {
76              LOG("Need to Reallocate Buffer, Free it First: %p", buffer);
77              pd->buffer_list = eina_list_remove(pd->buffer_list, buffer);
78              ecore_buffer_free(buffer);
79 
80              buffer = ecore_buffer_new("shm", w, h, format, 0);
81              pd->buffer_list = eina_list_append(pd->buffer_list, buffer);
82              LOG("Create Buffer: %p", buffer);
83           }
84      }
85 
86    return buffer;
87 }
88 
89 static void
paint_pixels(void * image,int padding,int width,int height,uint32_t time)90 paint_pixels(void *image, int padding, int width, int height, uint32_t time)
91 {
92    const int halfh = padding + (height - padding * 2) / 2;
93    const int halfw = padding + (width  - padding * 2) / 2;
94    int ir, or;
95    uint32_t *pixel = image;
96    int y;
97 
98    /* squared radii thresholds */
99    or = (halfw < halfh ? halfw : halfh) - 8;
100    ir = or - 32;
101    or *= or;
102    ir *= ir;
103 
104    pixel += padding * width;
105    for (y = padding; y < height - padding; y++) {
106         int x;
107         int y2 = (y - halfh) * (y - halfh);
108 
109         pixel += padding;
110         for (x = padding; x < width - padding; x++) {
111              uint32_t v;
112 
113              /* squared distance from center */
114              int r2 = (x - halfw) * (x - halfw) + y2;
115 
116              if (r2 < ir)
117                v = (r2 / 32 + time / 64) * 0x0080401;
118              else if (r2 < or)
119                v = (y + time / 32) * 0x0080401;
120              else
121                v = (x + time / 16) * 0x0080401;
122              v &= 0x00ffffff;
123              v |= 0xff000000;
124 
125              *pixel++ = v;
126         }
127 
128         pixel += padding;
129    }
130 }
131 
132 static Eina_Bool
_cb_render_post(void * data)133 _cb_render_post(void *data)
134 {
135    Provider_Data *pd = (Provider_Data *)data;
136    Ecore_Buffer *next_buffer = NULL;
137 
138    LOG("Startup - Post Render");
139 
140    LOG("Submit Buffer - buffer: %p", pd->buffer);
141    ecore_buffer_provider_buffer_enqueue(pd->provider, pd->buffer);
142    pd->buffer = NULL;
143 
144    next_buffer = _provider_buffer_get(pd, pd->w, pd->h, ECORE_BUFFER_FORMAT_XRGB8888);
145    if (next_buffer)
146      {
147         LOG("Drawable Buffer is Existed, ADD Render job again - buffer:%p", next_buffer);
148         pd->buffer = next_buffer;
149         _provider_render_queue(pd);
150      }
151 
152    ecore_idle_enterer_del(pd->post_render);
153    pd->post_render = NULL;
154 
155    LOG("Done - Post Render");
156 
157    return ECORE_CALLBACK_RENEW;
158 }
159 
160 static void
_provider_cb_render_job(void * data)161 _provider_cb_render_job(void *data)
162 {
163    Provider_Data *pd = (Provider_Data *)data;
164 
165    LOG("Startup - Render");
166 
167    if (!pd->buffer)
168      {
169         pd->buffer = _provider_buffer_get(pd,
170                                           pd->w, pd->h, ECORE_BUFFER_FORMAT_XRGB8888);
171      }
172 
173    if (pd->buffer)
174      {
175         void *data;
176 
177         LOG("Success to get Drawable Buffer, Drawing now... - buffer:%p", pd->buffer);
178         // Drawing...
179         data = ecore_buffer_data_get(pd->buffer);
180         paint_pixels(data, 0, pd->w, pd->h, ecore_loop_time_get() * 1000);
181 
182         if (!pd->post_render)
183           {
184              pd->post_render =
185                 ecore_idle_enterer_before_add(_cb_render_post, pd);
186           }
187      }
188 
189    ecore_job_del(pd->render_job);
190    pd->render_job = NULL;
191 }
192 
193 static void
_provider_render_queue(Provider_Data * pd)194 _provider_render_queue(Provider_Data *pd)
195 {
196    if (!pd) return;
197 
198    LOG("Render Queue");
199 
200    if (!pd->render_job)
201      pd->render_job = ecore_job_add(_provider_cb_render_job, pd);
202 }
203 
204 static void
_cb_consumer_add(Ecore_Buffer_Provider * provider EINA_UNUSED,int queue_size EINA_UNUSED,int w,int h,void * data)205 _cb_consumer_add(Ecore_Buffer_Provider *provider EINA_UNUSED, int queue_size EINA_UNUSED, int w, int h, void *data)
206 {
207    Provider_Data *pd = (Provider_Data *)data;
208 
209    LOG("Connected with Consumer, Now We can use Ecore_Buffer_Queue - queue_size:%d, geo(%dx%d)",
210        queue_size, w, h);
211 
212    pd->w = w;
213    pd->h = h;
214 
215    _provider_render_queue(pd);
216 }
217 
218 static void
_cb_consumer_del(Ecore_Buffer_Provider * provider EINA_UNUSED,void * data EINA_UNUSED)219 _cb_consumer_del(Ecore_Buffer_Provider *provider EINA_UNUSED, void *data EINA_UNUSED)
220 {
221    LOG("Disconnected with Consumer, Shutdown Provider now.");
222 
223    ecore_main_loop_quit();
224 }
225 
226 static void
_cb_buffer_released(Ecore_Buffer_Provider * provider EINA_UNUSED,void * data)227 _cb_buffer_released(Ecore_Buffer_Provider *provider EINA_UNUSED, void *data)
228 {
229    Provider_Data *pd = (Provider_Data *)data;
230 
231    LOG("Buffer Enqueued");
232 
233    _provider_render_queue(pd);
234 }
235 
236 int
main(void)237 main(void)
238 {
239    Provider_Data *pd;
240 
241    if (!init_all())
242      {
243         LOG("Initializing failed");
244         return -1;
245      }
246 
247    pd = (Provider_Data *)calloc(1, sizeof(Provider_Data));
248 
249    if (!pd || !(pd->provider = ecore_buffer_provider_new(name)))
250      {
251         LOG("Failed to create provider");
252         goto shutdown;
253      }
254 
255    ecore_buffer_provider_consumer_add_cb_set(pd->provider, _cb_consumer_add, pd);
256    ecore_buffer_provider_consumer_del_cb_set(pd->provider, _cb_consumer_del, pd);
257    ecore_buffer_provider_buffer_released_cb_set(pd->provider, _cb_buffer_released, pd);
258 
259    ecore_main_loop_begin();
260 
261 shutdown:
262    if (pd->buffer_list)
263      {
264         Ecore_Buffer *b;
265 
266         EINA_LIST_FREE(pd->buffer_list, b)
267            ecore_buffer_free(b);
268      }
269    if (pd->provider) ecore_buffer_provider_free(pd->provider);
270    free(pd);
271 
272    shutdown_all();
273    return 0;
274 }
275