summaryrefslogtreecommitdiff
path: root/src/lib/ecore_buffer/ecore_buffer_consumer.c
diff options
context:
space:
mode:
authorSeunghun Lee <beauty.positive3@gmail.com>2015-06-22 10:23:54 -0400
committerChris Michael <cp.michael@samsung.com>2015-06-22 10:31:42 -0400
commit8b621775619b9959fe952b095b3baaa7aaa99572 (patch)
tree99059a841a79729cac4687ea41f3abf672e6e455 /src/lib/ecore_buffer/ecore_buffer_consumer.c
parent3671506ad39d2a956e388e151bd20f1b9ffd62a5 (diff)
ecore-buffer: Add ecore_buffer library to EFL.
Summary: Ecore_Buffer is abstraction of graphic buffer. it supports backend of shm, x11_dri2 and x11_dri3 for now, and this library also provides method to share buffers between processes. Ecore_Buffer_Provider and Ecore_Buffer_Consumer is for this, sharing buffer. provider draws something in to Ecore_Buffer, and consumer receives and displays it. the binary, bq_mgr is a connection maker for buffer provider and consumer. it can be included Enlightenment as a deamon later. @feature Test Plan: 1. Configure with --enable-ecore-buffer and --enable-always-build-examples to build examples. 2. Run bq_mgr, it connects consumer and provider. 3. Run ecore_buffer_provider_example and ecore_buffer_consumer_example Reviewers: lsj119, gwanglim, cedric, zmike, jpeg, raster, devilhorns Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D2197
Diffstat (limited to 'src/lib/ecore_buffer/ecore_buffer_consumer.c')
-rw-r--r--src/lib/ecore_buffer/ecore_buffer_consumer.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/lib/ecore_buffer/ecore_buffer_consumer.c b/src/lib/ecore_buffer/ecore_buffer_consumer.c
new file mode 100644
index 0000000000..59a4a046cf
--- /dev/null
+++ b/src/lib/ecore_buffer/ecore_buffer_consumer.c
@@ -0,0 +1,417 @@
1#include <stdio.h>
2#include <unistd.h>
3
4#include <Eina.h>
5#include <Ecore_Buffer.h>
6#include <Ecore_Buffer_Queue.h>
7
8#include "bq_mgr_protocol.h"
9#include "shared_buffer.h"
10#include "buffer_queue.h"
11#include "ecore_buffer_private.h"
12#include "ecore_buffer_con.h"
13
14struct _Ecore_Buffer_Consumer
15{
16 struct bq_consumer *resource;
17 Ecore_Buffer_Queue *ebq;
18 struct
19 {
20 void (*provider_add) (Ecore_Buffer_Consumer *consumer, void *data);
21 void (*provider_del) (Ecore_Buffer_Consumer *consumer, void *data);
22 void (*enqueue) (Ecore_Buffer_Consumer *consumer, void *data);
23 void *data;
24 } cb;
25};
26
27static void _ecore_buffer_consumer_cb_provider_connected(void *data, struct bq_consumer *bq_consumer);
28static void _ecore_buffer_consumer_cb_provider_disconnected(void *data, struct bq_consumer *bq_consumer);
29static void _ecore_buffer_consumer_cb_buffer_attached(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *id, const char *engine, int32_t width, int32_t height, int32_t format, uint32_t flags);
30static void _ecore_buffer_consumer_cb_buffer_id_set(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, int32_t id, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2);
31static void _ecore_buffer_consumer_cb_buffer_fd_set(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, int32_t fd, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2);
32static void _ecore_buffer_consumer_cb_buffer_detached(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *id);
33static void _ecore_buffer_consumer_cb_add_buffer(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, uint32_t serial);
34static void _ecore_buffer_consumer_cb_buffer_free(Ecore_Buffer *buf, void *data);
35static Eina_Bool _ecore_buffer_consumer_buffer_import(Ecore_Buffer_Consumer *consumer, Shared_Buffer *sb, int32_t seed, Ecore_Export_Type export_type);
36
37struct bq_consumer_listener _ecore_buffer_consumer_listener =
38{
39 _ecore_buffer_consumer_cb_provider_connected,
40 _ecore_buffer_consumer_cb_provider_disconnected,
41 _ecore_buffer_consumer_cb_buffer_attached,
42 _ecore_buffer_consumer_cb_buffer_id_set,
43 _ecore_buffer_consumer_cb_buffer_fd_set,
44 _ecore_buffer_consumer_cb_buffer_detached,
45 _ecore_buffer_consumer_cb_add_buffer
46};
47
48EAPI Ecore_Buffer_Consumer *
49ecore_buffer_consumer_new(const char *name, int32_t queue_size, int32_t w, int32_t h)
50{
51 Ecore_Buffer_Consumer *consumer;
52 const int default_queue_size = 2;
53
54 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
55
56 DBG("Consumer New - name %s, queue size %d, size (%dx%d)",
57 name, queue_size, w, h);
58
59 if ((w < 1) || (h < 1))
60 return NULL;
61
62 if (queue_size < default_queue_size)
63 queue_size = default_queue_size;
64
65 _ecore_buffer_con_init_wait();
66
67 consumer = calloc(1, sizeof(Ecore_Buffer_Consumer));
68 if (!consumer)
69 return NULL;
70
71 consumer->ebq = _ecore_buffer_queue_new(w, h, queue_size);
72 if (!consumer->ebq)
73 {
74 free(consumer);
75 return NULL;
76 }
77
78 consumer->resource = _ecore_buffer_con_consumer_create(name, queue_size, w, h);
79 if (!consumer->resource)
80 {
81 _ecore_buffer_queue_free(consumer->ebq);
82 free(consumer);
83 return NULL;
84 }
85
86 bq_consumer_add_listener(consumer->resource,
87 &_ecore_buffer_consumer_listener,
88 consumer);
89
90 return consumer;
91}
92
93EAPI void
94ecore_buffer_consumer_free(Ecore_Buffer_Consumer *consumer)
95{
96 EINA_SAFETY_ON_NULL_RETURN(consumer);
97
98 DBG("Consumer Free");
99
100 if (consumer->ebq)
101 _ecore_buffer_queue_free(consumer->ebq);
102
103 if (consumer->resource)
104 bq_consumer_destroy(consumer->resource);
105
106 free(consumer);
107}
108
109EAPI Eina_Bool
110ecore_buffer_consumer_buffer_release(Ecore_Buffer_Consumer *consumer, Ecore_Buffer *buffer)
111{
112 Shared_Buffer *sb;
113
114 EINA_SAFETY_ON_NULL_RETURN_VAL(consumer, EINA_FALSE);
115 EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
116
117 DBG("Buffer Release");
118
119 if (!_ecore_buffer_queue_connection_state_get(consumer->ebq))
120 {
121 WARN("NOT Connected with provider yet");
122 return EINA_FALSE;
123 }
124
125 if (!(sb = _ecore_buffer_queue_shared_buffer_find(consumer->ebq, buffer)))
126 {
127 WARN("NOT shared - buffer %p", buffer);
128 return EINA_FALSE;
129 }
130
131 // already detached buffer, free buffer by deputy.
132 if (_shared_buffer_state_get(sb) == SHARED_BUFFER_STATE_DETACH)
133 {
134 DBG("Free buffer - buffer %p", sb);
135 ecore_buffer_free(buffer);
136 }
137 else
138 {
139 if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_DEQUEUE)
140 {
141 WARN("Failed to Release Buffer -"
142 "DO NOT Release buffer which is not Dequeued: buffer %p state %s",
143 sb, _shared_buffer_state_string_get(sb));
144 return EINA_FALSE;
145 }
146
147 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_RELEASE);
148 bq_consumer_release_buffer(consumer->resource, _shared_buffer_resource_get(sb));
149 }
150
151 return EINA_TRUE;
152}
153
154EAPI Ecore_Buffer *
155ecore_buffer_consumer_buffer_dequeue(Ecore_Buffer_Consumer *consumer)
156{
157 Shared_Buffer *sb;
158
159 EINA_SAFETY_ON_NULL_RETURN_VAL(consumer, EINA_FALSE);
160
161 DBG("Buffer Acquire");
162
163 if (!_ecore_buffer_queue_dequeue(consumer->ebq, &sb))
164 {
165 DBG("No Available Buffer in Queue");
166 return NULL;
167 }
168
169 // This should not happen.
170 if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_ENQUEUE)
171 {
172 ERR("Unknown error occured - Not on Enqueued State: buffer %p, state %s",
173 sb, _shared_buffer_state_string_get(sb));
174 return NULL;
175 }
176
177 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_DEQUEUE);
178
179 return _shared_buffer_buffer_get(sb);
180}
181
182EAPI Eina_Bool
183ecore_buffer_consumer_queue_is_empty(Ecore_Buffer_Consumer *consumer)
184{
185 EINA_SAFETY_ON_NULL_RETURN_VAL(consumer, EINA_FALSE);
186
187 return _ecore_buffer_queue_is_empty(consumer->ebq);
188}
189
190EAPI void
191ecore_buffer_consumer_provider_add_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Add_Cb func, void *data)
192{
193 EINA_SAFETY_ON_NULL_RETURN(consumer);
194
195 consumer->cb.provider_add = func;
196 consumer->cb.data = data;
197}
198
199EAPI void
200ecore_buffer_consumer_provider_del_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Del_Cb func, void *data)
201{
202 EINA_SAFETY_ON_NULL_RETURN(consumer);
203
204 consumer->cb.provider_del = func;
205 consumer->cb.data = data;
206}
207
208EAPI void
209ecore_buffer_consumer_buffer_enqueued_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Enqueue_Cb func, void *data)
210{
211 EINA_SAFETY_ON_NULL_RETURN(consumer);
212
213 consumer->cb.enqueue = func;
214 consumer->cb.data = data;
215}
216
217static void
218_ecore_buffer_consumer_cb_provider_connected(void *data, struct bq_consumer *bq_consumer EINA_UNUSED)
219{
220 Ecore_Buffer_Consumer *consumer = data;
221
222 EINA_SAFETY_ON_NULL_RETURN(consumer);
223
224 DBG("Provider Connected");
225
226 _ecore_buffer_queue_connection_state_set(consumer->ebq, EINA_TRUE);
227
228 CALLBACK_CALL(consumer, provider_add);
229}
230
231static void
232_ecore_buffer_consumer_cb_provider_disconnected(void *data, struct bq_consumer *bq_consumer EINA_UNUSED)
233{
234 Ecore_Buffer_Consumer *consumer = data;
235 Eina_List *clone, *shared_buffers, *l;
236 Shared_Buffer *sb;
237
238 EINA_SAFETY_ON_NULL_RETURN(consumer);
239
240 DBG("Provider Disconnected");
241
242 _ecore_buffer_queue_connection_state_set(consumer->ebq, EINA_FALSE);
243
244 CALLBACK_CALL(consumer, provider_del);
245
246 shared_buffers = _ecore_buffer_queue_shared_buffer_list_get(consumer->ebq);
247 clone = eina_list_clone(shared_buffers);
248
249 EINA_LIST_FOREACH(clone, l, sb)
250 ecore_buffer_free(_shared_buffer_buffer_get(sb));
251
252 eina_list_free(clone);
253}
254
255static void
256_ecore_buffer_consumer_cb_buffer_attached(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *id, const char *engine, int32_t width, int32_t height, int32_t format, uint32_t flags)
257{
258 Ecore_Buffer_Consumer *consumer = data;
259 Shared_Buffer *sb;
260
261 EINA_SAFETY_ON_NULL_RETURN(consumer);
262 EINA_SAFETY_ON_NULL_RETURN(consumer->ebq);
263
264 DBG("Buffer Attached - engine %s, size (%dx%d), format %d, flags %d",
265 engine, width, height, format, flags);
266
267 sb = _shared_buffer_new(engine, id, width, height, format, flags);
268 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ATTACH);
269 _ecore_buffer_queue_shared_buffer_add(consumer->ebq, sb);
270 bq_buffer_set_user_data(id, sb);
271}
272
273static void
274_ecore_buffer_consumer_cb_buffer_free(Ecore_Buffer *buf, void *data)
275{
276 Ecore_Buffer_Consumer *consumer = data;
277 Shared_Buffer *sb;
278
279 EINA_SAFETY_ON_NULL_RETURN(buf);
280 EINA_SAFETY_ON_NULL_RETURN(consumer);
281
282 sb = _ecore_buffer_queue_shared_buffer_find(consumer->ebq, buf);
283 if (!sb)
284 return;
285
286 _ecore_buffer_queue_shared_buffer_remove(consumer->ebq, sb);
287 bq_buffer_destroy(_shared_buffer_resource_get(sb));
288 _shared_buffer_free(sb);
289}
290
291static void
292_ecore_buffer_consumer_cb_buffer_id_set(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, int32_t id, int32_t offset0 EINA_UNUSED, int32_t stride0 EINA_UNUSED, int32_t offset1 EINA_UNUSED, int32_t stride1 EINA_UNUSED, int32_t offset2 EINA_UNUSED, int32_t stride2 EINA_UNUSED)
293{
294 Ecore_Buffer_Consumer *consumer = data;
295 Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
296
297 EINA_SAFETY_ON_NULL_RETURN(consumer);
298 EINA_SAFETY_ON_NULL_RETURN(sb);
299
300 if (_ecore_buffer_consumer_buffer_import(consumer, sb, id, EXPORT_TYPE_ID))
301 bq_buffer_set_user_data(buffer, sb);
302 else
303 ERR("Failed to import buffer - buffer resource %p", buffer);
304}
305
306static void
307_ecore_buffer_consumer_cb_buffer_fd_set(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, int32_t fd, int32_t offset0 EINA_UNUSED, int32_t stride0 EINA_UNUSED, int32_t offset1 EINA_UNUSED, int32_t stride1 EINA_UNUSED, int32_t offset2 EINA_UNUSED, int32_t stride2 EINA_UNUSED)
308{
309 Ecore_Buffer_Consumer *consumer = data;
310 Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
311
312 EINA_SAFETY_ON_NULL_RETURN(consumer);
313 EINA_SAFETY_ON_NULL_RETURN(sb);
314
315 if (_ecore_buffer_consumer_buffer_import(consumer, sb, fd, EXPORT_TYPE_FD))
316 bq_buffer_set_user_data(buffer, sb);
317 else
318 ERR("Failed to import buffer - buffer resource %p", buffer);
319}
320
321static void
322_ecore_buffer_consumer_cb_buffer_detached(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *id)
323{
324 Ecore_Buffer_Consumer *consumer = data;
325 Shared_Buffer *sb = bq_buffer_get_user_data(id);
326
327 EINA_SAFETY_ON_NULL_RETURN(consumer);
328 EINA_SAFETY_ON_NULL_RETURN(sb);
329
330 DBG("Buffer Detached");
331
332 // buffer is owned by consumer. free right now.
333 if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_DEQUEUE)
334 {
335 DBG("Free buffer - buffer %p, state %s",
336 sb, _shared_buffer_state_string_get(sb));
337 ecore_buffer_free(_shared_buffer_buffer_get(sb));
338 return;
339 }
340
341 // mark it as a detached buffer, and then free on buffer release time.
342 DBG("Just mark this buffer to free it when released - buffer %p, state %s",
343 sb, "SHARED_BUFFER_STATE_DEQUEUE");
344 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_DETACH);
345}
346
347static void
348_ecore_buffer_consumer_cb_add_buffer(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, uint32_t serial EINA_UNUSED)
349{
350 Ecore_Buffer_Consumer *consumer = data;
351 Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
352 Shared_Buffer_State state;
353
354 EINA_SAFETY_ON_NULL_RETURN(consumer);
355
356 DBG("Buffer Enqueued");
357
358 if (!sb)
359 {
360 ERR("Unknown Error occured - maybe this buffer is not shared yet");
361 return;
362 }
363
364 state = _shared_buffer_state_get(sb);
365 if ((state != SHARED_BUFFER_STATE_IMPORT) &&
366 (state != SHARED_BUFFER_STATE_RELEASE))
367 {
368 ERR("Unknown Error occured - Could not enqueued this state of buffer: buffer %p, state %s",
369 sb, _shared_buffer_state_string_get(sb));
370 return;
371 }
372
373 _ecore_buffer_queue_enqueue(consumer->ebq, sb);
374 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ENQUEUE);
375
376 CALLBACK_CALL(consumer, enqueue);
377}
378
379static Eina_Bool
380_ecore_buffer_consumer_buffer_import(Ecore_Buffer_Consumer *consumer, Shared_Buffer *sb, int32_t seed, Ecore_Export_Type export_type)
381{
382 Ecore_Buffer *buffer;
383 const char *engine = NULL;
384 int w, h, format;
385 unsigned int flags;
386
387 if ((!sb) ||
388 (!_shared_buffer_info_get(sb, &engine, &w, &h, &format, &flags)))
389 {
390 ERR("Failed to Get Shared Buffer");
391 return EINA_FALSE;
392 }
393
394 if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_ATTACH)
395 {
396 ERR("Not Attached Buffer - buffer %p state %s",
397 sb, _shared_buffer_state_string_get(sb));
398 return EINA_FALSE;
399 }
400
401 if (!(buffer = _ecore_buffer_import(engine, w, h, format, export_type, seed, flags)))
402 {
403 ERR("Failed to Import Buffer - size (%dx%d), foramt %d, seed %d, export_type %d",
404 w, h, format, seed, export_type);
405 return EINA_FALSE;
406 }
407
408 if (export_type == EXPORT_TYPE_FD)
409 close(seed);
410
411 _shared_buffer_buffer_set(sb, buffer);
412 _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_IMPORT);
413
414 ecore_buffer_free_callback_add(buffer, _ecore_buffer_consumer_cb_buffer_free, consumer);
415
416 return EINA_TRUE;
417}