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