include config.h in all c file and fixed dlog level
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include "tbm_bufmgr_int.h"
35 #include "list.h"
36
37 #define FREE_QUEUE      1
38 #define DIRTY_QUEUE     2
39 #define NODE_LIST       4
40
41 #define TBM_QUEUE_DEBUG 0
42
43 #ifdef TRACE
44 #define TBM_QUEUE_TRACE(fmt, ...)  { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
45 #else
46 #define TBM_QUEUE_TRACE(fmt, ...)
47 #endif /* TRACE */
48
49 #if TBM_QUEUE_DEBUG
50 #define TBM_LOCK() TBM_LOG_D("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
51 #define TBM_UNLOCK() TBM_LOG_D("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
52 #else
53 #define TBM_LOCK()
54 #define TBM_UNLOCK()
55 #endif
56
57 static tbm_bufmgr g_surf_queue_bufmgr;
58 static pthread_mutex_t tbm_surf_queue_lock;
59 void _tbm_surface_queue_mutex_unlock(void);
60
61 /* check condition */
62 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
63         if (!(cond)) {\
64                 TBM_LOG_E("'%s' failed.\n", #cond);\
65                 _tbm_surf_queue_mutex_unlock();\
66                 return;\
67         } \
68 }
69
70 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
71         if (!(cond)) {\
72                 TBM_LOG_E("'%s' failed.\n", #cond);\
73                 _tbm_surf_queue_mutex_unlock();\
74                 return val;\
75         } \
76 }
77
78 typedef enum _queue_node_type {
79         QUEUE_NODE_TYPE_NONE,
80         QUEUE_NODE_TYPE_DEQUEUE,
81         QUEUE_NODE_TYPE_ENQUEUE,
82         QUEUE_NODE_TYPE_ACQUIRE,
83         QUEUE_NODE_TYPE_RELEASE
84 } Queue_Node_Type;
85
86 typedef struct {
87         struct list_head head;
88         int count;
89 } queue;
90
91 typedef struct {
92         tbm_surface_h surface;
93
94         struct list_head item_link;
95         struct list_head link;
96
97         Queue_Node_Type type;
98
99         unsigned int priv_flags;        /*for each queue*/
100 } queue_node;
101
102 typedef struct {
103         struct list_head link;
104
105         tbm_surface_queue_notify_cb cb;
106         void *data;
107 } queue_notify;
108
109 typedef struct _tbm_surface_queue_interface {
110         void (*init)(tbm_surface_queue_h queue);
111         void (*reset)(tbm_surface_queue_h queue);
112         void (*destroy)(tbm_surface_queue_h queue);
113         void (*need_attach)(tbm_surface_queue_h queue);
114
115         void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
116         void (*release)(tbm_surface_queue_h queue, queue_node *node);
117         queue_node *(*dequeue)(tbm_surface_queue_h queue);
118         queue_node *(*acquire)(tbm_surface_queue_h queue);
119 } tbm_surface_queue_interface;
120
121 struct _tbm_surface_queue {
122         int width;
123         int height;
124         int format;
125         int queue_size;
126
127         queue free_queue;
128         queue dirty_queue;
129         struct list_head list;
130
131         struct list_head destory_noti;
132         struct list_head dequeuable_noti;
133         struct list_head dequeue_noti;
134         struct list_head acquirable_noti;
135         struct list_head reset_noti;
136
137         pthread_mutex_t lock;
138         pthread_cond_t free_cond;
139         pthread_cond_t dirty_cond;
140
141         const tbm_surface_queue_interface *impl;
142         void *impl_data;
143
144         //For external buffer allocation
145         tbm_surface_alloc_cb alloc_cb;
146         tbm_surface_free_cb free_cb;
147         void *alloc_cb_data;
148
149         struct list_head item_link; /* link of surface queue */
150 };
151
152 /* LCOV_EXCL_START */
153
154 static bool
155 _tbm_surf_queue_mutex_init(void)
156 {
157         static bool tbm_surf_queue_mutex_init = false;
158
159         if (tbm_surf_queue_mutex_init)
160                 return true;
161
162         if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
163                 TBM_LOG_E("fail: tbm_surf_queue mutex init\n");
164                 return false;
165         }
166
167         tbm_surf_queue_mutex_init = true;
168
169         return true;
170 }
171
172 void
173 _tbm_surf_queue_mutex_lock(void)
174 {
175         if (!_tbm_surf_queue_mutex_init())
176                 return;
177
178         pthread_mutex_lock(&tbm_surf_queue_lock);
179 }
180
181 void
182 _tbm_surf_queue_mutex_unlock(void)
183 {
184         pthread_mutex_unlock(&tbm_surf_queue_lock);
185 }
186
187 static void
188 _init_tbm_surf_queue_bufmgr(void)
189 {
190         g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
191 }
192
193 static void
194 _deinit_tbm_surf_queue_bufmgr(void)
195 {
196         if (!g_surf_queue_bufmgr)
197                 return;
198
199         tbm_bufmgr_deinit(g_surf_queue_bufmgr);
200         g_surf_queue_bufmgr = NULL;
201 }
202
203 static int
204 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
205 {
206         tbm_surface_queue_h old_data = NULL, tmp = NULL;
207
208         if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
209                 TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue);
210                 return 0;
211         }
212
213         if (!LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
214                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surf_queue_bufmgr->surf_queue_list, item_link) {
215                         if (old_data == surface_queue) {
216                                 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
217                                 return 1;
218                         }
219                 }
220         }
221         TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue);
222         return 0;
223 }
224
225 static queue_node *
226 _queue_node_create(void)
227 {
228         queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
229
230         TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
231
232         return node;
233 }
234
235 static void
236 _queue_node_delete(queue_node *node)
237 {
238         LIST_DEL(&node->item_link);
239         LIST_DEL(&node->link);
240         free(node);
241 }
242
243 static int
244 _queue_is_empty(queue *queue)
245 {
246         if (LIST_IS_EMPTY(&queue->head))
247                 return 1;
248
249         return 0;
250 }
251
252 static void
253 _queue_node_push_back(queue *queue, queue_node *node)
254 {
255         LIST_ADDTAIL(&node->item_link, &queue->head);
256         queue->count++;
257 }
258
259 static void
260 _queue_node_push_front(queue *queue, queue_node *node)
261 {
262         LIST_ADD(&node->item_link, &queue->head);
263         queue->count++;
264 }
265
266 static queue_node *
267 _queue_node_pop_front(queue *queue)
268 {
269         queue_node *node = NULL;
270
271         node = LIST_ENTRY(queue_node, queue->head.next, item_link);
272
273         LIST_DEL(&node->item_link);
274         queue->count--;
275
276         return node;
277 }
278
279 static queue_node *
280 _queue_node_pop(queue *queue, queue_node *node)
281 {
282         LIST_DEL(&node->item_link);
283         queue->count--;
284
285         return node;
286 }
287
288 static queue_node *
289 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
290                 tbm_surface_h surface, int *out_type)
291 {
292         queue_node *node = NULL;
293         queue_node *tmp = NULL;
294
295         if (type == 0)
296                 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
297         if (out_type)
298                 *out_type = 0;
299
300         if (type & FREE_QUEUE) {
301                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
302                                          item_link) {
303                         if (node->surface == surface) {
304                                 if (out_type)
305                                         *out_type = FREE_QUEUE;
306
307                                 return node;
308                         }
309                 }
310         }
311
312         if (type & DIRTY_QUEUE) {
313                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
314                                          item_link) {
315                         if (node->surface == surface) {
316                                 if (out_type)
317                                         *out_type = DIRTY_QUEUE;
318
319                                 return node;
320                         }
321                 }
322         }
323
324         if (type & NODE_LIST) {
325                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
326                         if (node->surface == surface) {
327                                 if (out_type)
328                                         *out_type = NODE_LIST;
329
330                                 return node;
331                         }
332                 }
333         }
334
335         return NULL;
336 }
337
338 static void
339 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
340 {
341         if (node->surface) {
342                 if (surface_queue->free_cb) {
343                         surface_queue->free_cb(surface_queue,
344                                         surface_queue->alloc_cb_data,
345                                         node->surface);
346                 }
347
348                 tbm_surface_destroy(node->surface);
349         }
350
351         _queue_node_delete(node);
352 }
353
354 static void
355 _queue_init(queue *queue)
356 {
357         LIST_INITHEAD(&queue->head);
358
359         queue->count = 0;
360 }
361
362 static void
363 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
364             void *data)
365 {
366         TBM_RETURN_IF_FAIL(cb != NULL);
367
368         queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
369
370         TBM_RETURN_IF_FAIL(item != NULL);
371
372         LIST_INITHEAD(&item->link);
373         item->cb = cb;
374         item->data = data;
375
376         LIST_ADDTAIL(&item->link, list);
377 }
378
379 static void
380 _notify_remove(struct list_head *list,
381                tbm_surface_queue_notify_cb cb, void *data)
382 {
383         queue_notify *item = NULL, *tmp = NULL;
384
385         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
386                 if (item->cb == cb && item->data == data) {
387                         LIST_DEL(&item->link);
388                         free(item);
389                         return;
390                 }
391         }
392
393         TBM_LOG_E("Cannot find notifiy\n");
394 }
395
396 static void
397 _notify_remove_all(struct list_head *list)
398 {
399         queue_notify *item = NULL, *tmp = NULL;
400
401         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
402                 LIST_DEL(&item->link);
403                 free(item);
404         }
405 }
406
407 static void
408 _notify_emit(tbm_surface_queue_h surface_queue,
409              struct list_head *list)
410 {
411         queue_notify *item = NULL, *tmp = NULL;
412
413         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
414                 item->cb(surface_queue, item->data);
415         }
416 }
417
418 static int
419 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
420 {
421         queue_node *node = NULL;
422         queue_node *tmp = NULL;
423         int count = 0;
424
425         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
426                 if (node->type == type)
427                         count++;
428         }
429
430         return count;
431 }
432
433 void
434 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
435                           tbm_surface_h surface)
436 {
437         queue_node *node = NULL;
438
439         node = _queue_node_create();
440         TBM_RETURN_IF_FAIL(node != NULL);
441
442         tbm_surface_internal_ref(surface);
443         node->surface = surface;
444
445         LIST_ADDTAIL(&node->link, &surface_queue->list);
446         _queue_node_push_back(&surface_queue->free_queue, node);
447 }
448
449 void
450 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
451                           tbm_surface_h surface)
452 {
453         queue_node *node = NULL;
454         int queue_type;
455
456         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
457         if (node)
458                 _queue_delete_node(surface_queue, node);
459 }
460
461 void
462 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
463                            queue_node *node, int push_back)
464 {
465         if (push_back)
466                 _queue_node_push_back(&surface_queue->dirty_queue, node);
467         else
468                 _queue_node_push_front(&surface_queue->dirty_queue, node);
469 }
470
471 queue_node *
472 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
473 {
474         queue_node *node = NULL;
475
476         if (_queue_is_empty(&surface_queue->free_queue)) {
477                 if (surface_queue->impl && surface_queue->impl->need_attach)
478                         surface_queue->impl->need_attach(surface_queue);
479
480                 if (_queue_is_empty(&surface_queue->free_queue))
481                         return NULL;
482         }
483
484         node = _queue_node_pop_front(&surface_queue->free_queue);
485
486         return node;
487 }
488
489 queue_node *
490 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
491 {
492         queue_node *node = NULL;
493
494         if (_queue_is_empty(&surface_queue->dirty_queue))
495                 return NULL;
496
497         node = _queue_node_pop_front(&surface_queue->dirty_queue);
498
499         return node;
500 }
501
502 void
503 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
504                            queue_node *node, int push_back)
505 {
506         if (push_back)
507                 _queue_node_push_back(&surface_queue->free_queue, node);
508         else
509                 _queue_node_push_front(&surface_queue->free_queue, node);
510 }
511
512 void
513 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
514                         int queue_size,
515                         int width, int height, int format,
516                         const tbm_surface_queue_interface *impl, void *data)
517 {
518         TBM_RETURN_IF_FAIL(surface_queue != NULL);
519         TBM_RETURN_IF_FAIL(impl != NULL);
520
521         memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
522
523         if (!g_surf_queue_bufmgr)
524                 _init_tbm_surf_queue_bufmgr();
525
526         pthread_mutex_init(&surface_queue->lock, NULL);
527         pthread_cond_init(&surface_queue->free_cond, NULL);
528         pthread_cond_init(&surface_queue->dirty_cond, NULL);
529
530         surface_queue->queue_size = queue_size;
531         surface_queue->width = width;
532         surface_queue->height = height;
533         surface_queue->format = format;
534         surface_queue->impl = impl;
535         surface_queue->impl_data = data;
536
537         _queue_init(&surface_queue->free_queue);
538         _queue_init(&surface_queue->dirty_queue);
539         LIST_INITHEAD(&surface_queue->list);
540
541         LIST_INITHEAD(&surface_queue->destory_noti);
542         LIST_INITHEAD(&surface_queue->acquirable_noti);
543         LIST_INITHEAD(&surface_queue->dequeuable_noti);
544         LIST_INITHEAD(&surface_queue->dequeue_noti);
545         LIST_INITHEAD(&surface_queue->reset_noti);
546
547         if (surface_queue->impl && surface_queue->impl->init)
548                 surface_queue->impl->init(surface_queue);
549
550         LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
551 }
552
553 tbm_surface_queue_error_e
554 tbm_surface_queue_add_destroy_cb(
555         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
556         void *data)
557 {
558         _tbm_surf_queue_mutex_lock();
559
560         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
561                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
562
563         pthread_mutex_lock(&surface_queue->lock);
564
565         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
566
567         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
568
569         pthread_mutex_unlock(&surface_queue->lock);
570
571         _tbm_surf_queue_mutex_unlock();
572
573         return TBM_SURFACE_QUEUE_ERROR_NONE;
574 }
575
576 tbm_surface_queue_error_e
577 tbm_surface_queue_remove_destroy_cb(
578         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
579         void *data)
580 {
581         _tbm_surf_queue_mutex_lock();
582
583         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
584                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
585
586         pthread_mutex_lock(&surface_queue->lock);
587
588         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
589
590         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
591
592         pthread_mutex_unlock(&surface_queue->lock);
593
594         _tbm_surf_queue_mutex_unlock();
595
596         return TBM_SURFACE_QUEUE_ERROR_NONE;
597 }
598
599 tbm_surface_queue_error_e
600 tbm_surface_queue_add_dequeuable_cb(
601         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
602         void *data)
603 {
604         _tbm_surf_queue_mutex_lock();
605
606         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
607                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
608
609         pthread_mutex_lock(&surface_queue->lock);
610
611         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
612
613         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
614
615         pthread_mutex_unlock(&surface_queue->lock);
616
617         _tbm_surf_queue_mutex_unlock();
618
619         return TBM_SURFACE_QUEUE_ERROR_NONE;
620 }
621
622 tbm_surface_queue_error_e
623 tbm_surface_queue_remove_dequeuable_cb(
624         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
625         void *data)
626 {
627         _tbm_surf_queue_mutex_lock();
628
629         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
630                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
631
632         pthread_mutex_lock(&surface_queue->lock);
633
634         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
635
636         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
637
638         pthread_mutex_unlock(&surface_queue->lock);
639
640         _tbm_surf_queue_mutex_unlock();
641
642         return TBM_SURFACE_QUEUE_ERROR_NONE;
643 }
644
645 tbm_surface_queue_error_e
646 tbm_surface_queue_add_dequeue_cb(
647         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
648         void *data)
649 {
650         _tbm_surf_queue_mutex_lock();
651
652         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
653                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
654
655         pthread_mutex_lock(&surface_queue->lock);
656
657         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
658
659         _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
660
661         pthread_mutex_unlock(&surface_queue->lock);
662
663         _tbm_surf_queue_mutex_unlock();
664
665         return TBM_SURFACE_QUEUE_ERROR_NONE;
666 }
667
668 tbm_surface_queue_error_e
669 tbm_surface_queue_remove_dequeue_cb(
670         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
671         void *data)
672 {
673         _tbm_surf_queue_mutex_lock();
674
675         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
676                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
677
678         pthread_mutex_lock(&surface_queue->lock);
679
680         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
681
682         _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
683
684         pthread_mutex_unlock(&surface_queue->lock);
685
686         _tbm_surf_queue_mutex_unlock();
687
688         return TBM_SURFACE_QUEUE_ERROR_NONE;
689 }
690
691 tbm_surface_queue_error_e
692 tbm_surface_queue_add_acquirable_cb(
693         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
694         void *data)
695 {
696         _tbm_surf_queue_mutex_lock();
697
698         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
699                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
700
701         pthread_mutex_lock(&surface_queue->lock);
702
703         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
704
705         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
706
707         pthread_mutex_unlock(&surface_queue->lock);
708
709         _tbm_surf_queue_mutex_unlock();
710
711         return TBM_SURFACE_QUEUE_ERROR_NONE;
712 }
713
714 tbm_surface_queue_error_e
715 tbm_surface_queue_remove_acquirable_cb(
716         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
717         void *data)
718 {
719         _tbm_surf_queue_mutex_lock();
720
721         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
722                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
723
724         pthread_mutex_lock(&surface_queue->lock);
725
726         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
727
728         _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
729
730         pthread_mutex_unlock(&surface_queue->lock);
731
732         _tbm_surf_queue_mutex_unlock();
733
734         return TBM_SURFACE_QUEUE_ERROR_NONE;
735 }
736
737 tbm_surface_queue_error_e
738 tbm_surface_queue_set_alloc_cb(
739         tbm_surface_queue_h surface_queue,
740         tbm_surface_alloc_cb alloc_cb,
741         tbm_surface_free_cb free_cb,
742         void *data)
743 {
744         _tbm_surf_queue_mutex_lock();
745
746         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
747                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
748
749         pthread_mutex_lock(&surface_queue->lock);
750
751         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
752
753         surface_queue->alloc_cb = alloc_cb;
754         surface_queue->free_cb = free_cb;
755         surface_queue->alloc_cb_data = data;
756
757         pthread_mutex_unlock(&surface_queue->lock);
758
759         _tbm_surf_queue_mutex_unlock();
760
761         return TBM_SURFACE_QUEUE_ERROR_NONE;
762 }
763
764 int
765 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
766 {
767         int width;
768
769         _tbm_surf_queue_mutex_lock();
770
771         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
772
773         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
774
775         width = surface_queue->width;
776
777         _tbm_surf_queue_mutex_unlock();
778
779         return width;
780 }
781
782 int
783 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
784 {
785         int height;
786
787         _tbm_surf_queue_mutex_lock();
788
789         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
790
791         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
792
793         height = surface_queue->height;
794
795         _tbm_surf_queue_mutex_unlock();
796
797         return height;
798 }
799
800 int
801 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
802 {
803         int format;
804
805         _tbm_surf_queue_mutex_lock();
806
807         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
808
809         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
810
811         format = surface_queue->format;
812
813         _tbm_surf_queue_mutex_unlock();
814
815         return format;
816 }
817
818 int
819 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
820 {
821         int queue_size;
822
823         _tbm_surf_queue_mutex_lock();
824
825         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
826
827         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
828
829         queue_size = surface_queue->queue_size;
830
831         _tbm_surf_queue_mutex_unlock();
832
833         return queue_size;
834 }
835
836 tbm_surface_queue_error_e
837 tbm_surface_queue_add_reset_cb(
838         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
839         void *data)
840 {
841         _tbm_surf_queue_mutex_lock();
842
843         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
844                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
845
846         pthread_mutex_lock(&surface_queue->lock);
847
848         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
849
850         _notify_add(&surface_queue->reset_noti, reset_cb, data);
851
852         pthread_mutex_unlock(&surface_queue->lock);
853
854         _tbm_surf_queue_mutex_unlock();
855
856         return TBM_SURFACE_QUEUE_ERROR_NONE;
857 }
858
859 tbm_surface_queue_error_e
860 tbm_surface_queue_remove_reset_cb(
861         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
862         void *data)
863 {
864         _tbm_surf_queue_mutex_lock();
865
866         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
867                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
868
869         pthread_mutex_lock(&surface_queue->lock);
870
871         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
872
873         _notify_remove(&surface_queue->reset_noti, reset_cb, data);
874
875         pthread_mutex_unlock(&surface_queue->lock);
876
877         _tbm_surf_queue_mutex_unlock();
878
879         return TBM_SURFACE_QUEUE_ERROR_NONE;
880 }
881
882 tbm_surface_queue_error_e
883 tbm_surface_queue_enqueue(tbm_surface_queue_h
884                           surface_queue, tbm_surface_h surface)
885 {
886         queue_node *node = NULL;
887         int queue_type;
888
889         _tbm_surf_queue_mutex_lock();
890
891         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
892                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
893         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
894                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
895
896         if (b_dump_queue)
897                 tbm_surface_internal_dump_buffer(surface, "enqueue");
898
899         pthread_mutex_lock(&surface_queue->lock);
900
901         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
902
903         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
904         if (node == NULL || queue_type != NODE_LIST) {
905                 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
906                         node, queue_type);
907                 pthread_mutex_unlock(&surface_queue->lock);
908
909                 _tbm_surf_queue_mutex_unlock();
910                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
911         }
912
913         if (surface_queue->impl && surface_queue->impl->enqueue)
914                 surface_queue->impl->enqueue(surface_queue, node);
915         else
916                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
917
918         if (_queue_is_empty(&surface_queue->dirty_queue)) {
919                 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
920                 pthread_mutex_unlock(&surface_queue->lock);
921
922                 _tbm_surf_queue_mutex_unlock();
923                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
924         }
925
926         node->type = QUEUE_NODE_TYPE_ENQUEUE;
927
928         pthread_mutex_unlock(&surface_queue->lock);
929         pthread_cond_signal(&surface_queue->dirty_cond);
930
931         _tbm_surf_queue_mutex_unlock();
932
933         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
934
935         return TBM_SURFACE_QUEUE_ERROR_NONE;
936 }
937
938 tbm_surface_queue_error_e
939 tbm_surface_queue_dequeue(tbm_surface_queue_h
940                           surface_queue, tbm_surface_h *surface)
941 {
942         queue_node *node = NULL;
943
944         _tbm_surf_queue_mutex_lock();
945
946         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
947                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
948         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
949                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
950
951         pthread_mutex_lock(&surface_queue->lock);
952
953         if (surface_queue->impl && surface_queue->impl->dequeue)
954                 node = surface_queue->impl->dequeue(surface_queue);
955         else
956                 node = _tbm_surface_queue_dequeue(surface_queue);
957
958         if (node == NULL) {
959                 *surface = NULL;
960                 pthread_mutex_unlock(&surface_queue->lock);
961
962                 _tbm_surf_queue_mutex_unlock();
963                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
964         }
965
966         if (node->surface == NULL) {
967                 *surface = NULL;
968                 TBM_LOG_E("_queue_node_pop_front  failed\n");
969                 pthread_mutex_unlock(&surface_queue->lock);
970
971                 _tbm_surf_queue_mutex_unlock();
972                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
973         }
974
975         node->type = QUEUE_NODE_TYPE_DEQUEUE;
976         *surface = node->surface;
977
978         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
979
980         pthread_mutex_unlock(&surface_queue->lock);
981
982         _tbm_surf_queue_mutex_unlock();
983
984         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
985
986         return TBM_SURFACE_QUEUE_ERROR_NONE;
987 }
988
989 int
990 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
991 {
992         _tbm_surf_queue_mutex_lock();
993
994         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
995
996         pthread_mutex_lock(&surface_queue->lock);
997
998         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
999
1000         if (_queue_is_empty(&surface_queue->free_queue)) {
1001                 if (surface_queue->impl && surface_queue->impl->need_attach)
1002                         surface_queue->impl->need_attach(surface_queue);
1003
1004                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1005                                 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1006                                 _tbm_surf_queue_mutex_unlock();
1007                                 return 0;
1008                 }
1009         }
1010
1011         if (_queue_is_empty(&surface_queue->free_queue)) {
1012                 if (wait &&
1013                         _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) {
1014
1015                         _tbm_surf_queue_mutex_unlock();
1016
1017                         pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1018
1019                         _tbm_surf_queue_mutex_lock();
1020
1021                         if (!_tbm_surface_queue_is_valid(surface_queue)) {
1022                                   TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1023                                   _tbm_surf_queue_mutex_unlock();
1024                                   return 0;
1025                         }
1026
1027                         pthread_mutex_unlock(&surface_queue->lock);
1028
1029                         _tbm_surf_queue_mutex_unlock();
1030                         return 1;
1031                 }
1032
1033                 pthread_mutex_unlock(&surface_queue->lock);
1034
1035                 _tbm_surf_queue_mutex_unlock();
1036                 return 0;
1037         }
1038
1039         pthread_mutex_unlock(&surface_queue->lock);
1040
1041         _tbm_surf_queue_mutex_unlock();
1042
1043         return 1;
1044 }
1045
1046 tbm_surface_queue_error_e
1047 tbm_surface_queue_release(tbm_surface_queue_h
1048                           surface_queue, tbm_surface_h surface)
1049 {
1050         queue_node *node = NULL;
1051         int queue_type;
1052
1053         _tbm_surf_queue_mutex_lock();
1054
1055         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1056                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1057         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1058                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1059
1060         pthread_mutex_lock(&surface_queue->lock);
1061
1062         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1063
1064         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1065         if (node == NULL || queue_type != NODE_LIST) {
1066                 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
1067                         node, queue_type);
1068                 pthread_mutex_unlock(&surface_queue->lock);
1069
1070                 _tbm_surf_queue_mutex_unlock();
1071                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1072         }
1073
1074         if (surface_queue->impl && surface_queue->impl->release)
1075                 surface_queue->impl->release(surface_queue, node);
1076         else
1077                 _tbm_surface_queue_release(surface_queue, node, 1);
1078
1079         if (_queue_is_empty(&surface_queue->free_queue)) {
1080                 pthread_mutex_unlock(&surface_queue->lock);
1081
1082                 _tbm_surf_queue_mutex_unlock();
1083                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1084         }
1085
1086         node->type = QUEUE_NODE_TYPE_RELEASE;
1087
1088         pthread_mutex_unlock(&surface_queue->lock);
1089         pthread_cond_signal(&surface_queue->free_cond);
1090
1091         _tbm_surf_queue_mutex_unlock();
1092
1093         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1094
1095         return TBM_SURFACE_QUEUE_ERROR_NONE;
1096 }
1097
1098 tbm_surface_queue_error_e
1099 tbm_surface_queue_acquire(tbm_surface_queue_h
1100                           surface_queue, tbm_surface_h *surface)
1101 {
1102         queue_node *node = NULL;
1103
1104         _tbm_surf_queue_mutex_lock();
1105
1106         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1107                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1108         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1109                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1110
1111         pthread_mutex_lock(&surface_queue->lock);
1112
1113         if (surface_queue->impl && surface_queue->impl->acquire)
1114                 node = surface_queue->impl->acquire(surface_queue);
1115         else
1116                 node = _tbm_surface_queue_acquire(surface_queue);
1117
1118         if (node == NULL) {
1119                 *surface = NULL;
1120                 pthread_mutex_unlock(&surface_queue->lock);
1121
1122                 _tbm_surf_queue_mutex_unlock();
1123                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1124         }
1125
1126         if (node->surface == NULL) {
1127                 *surface = NULL;
1128                 TBM_LOG_E("_queue_node_pop_front  failed\n");
1129                 pthread_mutex_unlock(&surface_queue->lock);
1130
1131                 _tbm_surf_queue_mutex_unlock();
1132                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1133         }
1134
1135         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1136
1137         *surface = node->surface;
1138
1139         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1140
1141         pthread_mutex_unlock(&surface_queue->lock);
1142
1143         _tbm_surf_queue_mutex_unlock();
1144
1145         if (b_dump_queue)
1146                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1147
1148         return TBM_SURFACE_QUEUE_ERROR_NONE;
1149 }
1150
1151 int
1152 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1153 {
1154         _tbm_surf_queue_mutex_lock();
1155
1156         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1157
1158         pthread_mutex_lock(&surface_queue->lock);
1159
1160         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1161
1162         if (_queue_is_empty(&surface_queue->dirty_queue)) {
1163                 if (wait &&
1164                         _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
1165
1166                         _tbm_surf_queue_mutex_unlock();
1167
1168                         pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1169
1170                         _tbm_surf_queue_mutex_lock();
1171
1172                         if (!_tbm_surface_queue_is_valid(surface_queue)) {
1173                                   TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1174                                   _tbm_surf_queue_mutex_unlock();
1175                                   return 0;
1176                         }
1177
1178                         pthread_mutex_unlock(&surface_queue->lock);
1179
1180                         _tbm_surf_queue_mutex_unlock();
1181                         return 1;
1182                 }
1183
1184                 pthread_mutex_unlock(&surface_queue->lock);
1185
1186                 _tbm_surf_queue_mutex_unlock();
1187                 return 0;
1188         }
1189
1190         pthread_mutex_unlock(&surface_queue->lock);
1191
1192         _tbm_surf_queue_mutex_unlock();
1193
1194         return 1;
1195 }
1196
1197 void
1198 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1199 {
1200         queue_node *node = NULL, *tmp = NULL;
1201
1202         _tbm_surf_queue_mutex_lock();
1203
1204         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1205
1206         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1207
1208         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1209                 _queue_delete_node(surface_queue, node);
1210         }
1211
1212         if (surface_queue->impl && surface_queue->impl->destroy)
1213                 surface_queue->impl->destroy(surface_queue);
1214
1215         _notify_emit(surface_queue, &surface_queue->destory_noti);
1216
1217         _notify_remove_all(&surface_queue->destory_noti);
1218         _notify_remove_all(&surface_queue->acquirable_noti);
1219         _notify_remove_all(&surface_queue->dequeuable_noti);
1220         _notify_remove_all(&surface_queue->reset_noti);
1221
1222         pthread_mutex_destroy(&surface_queue->lock);
1223
1224         LIST_DEL(&surface_queue->item_link);
1225
1226         free(surface_queue);
1227         surface_queue = NULL;
1228
1229         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1230                 _deinit_tbm_surf_queue_bufmgr();
1231
1232         _tbm_surf_queue_mutex_unlock();
1233 }
1234
1235 tbm_surface_queue_error_e
1236 tbm_surface_queue_reset(tbm_surface_queue_h
1237                         surface_queue, int width, int height, int format)
1238 {
1239         queue_node *node = NULL, *tmp = NULL;
1240
1241         _tbm_surf_queue_mutex_lock();
1242
1243         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1244                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1245
1246         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1247
1248         if (width == surface_queue->width && height == surface_queue->height &&
1249             format == surface_queue->format) {
1250                 _tbm_surf_queue_mutex_unlock();
1251                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1252         }
1253
1254         pthread_mutex_lock(&surface_queue->lock);
1255
1256         surface_queue->width = width;
1257         surface_queue->height = height;
1258         surface_queue->format = format;
1259
1260         /* Destory surface and Push to free_queue */
1261         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1262                 _queue_delete_node(surface_queue, node);
1263         }
1264
1265         /* Reset queue */
1266         _queue_init(&surface_queue->free_queue);
1267         _queue_init(&surface_queue->dirty_queue);
1268         LIST_INITHEAD(&surface_queue->list);
1269
1270         if (surface_queue->impl && surface_queue->impl->reset)
1271                 surface_queue->impl->reset(surface_queue);
1272
1273         pthread_mutex_unlock(&surface_queue->lock);
1274         pthread_cond_signal(&surface_queue->free_cond);
1275
1276         _tbm_surf_queue_mutex_unlock();
1277
1278         _notify_emit(surface_queue, &surface_queue->reset_noti);
1279
1280         return TBM_SURFACE_QUEUE_ERROR_NONE;
1281 }
1282
1283 tbm_surface_queue_error_e
1284 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1285 {
1286         queue_node *node = NULL, *tmp = NULL;
1287
1288         _tbm_surf_queue_mutex_lock();
1289
1290         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1291                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1292
1293         pthread_mutex_lock(&surface_queue->lock);
1294
1295         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1296
1297         /* Destory surface and Push to free_queue */
1298         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1299                 _queue_delete_node(surface_queue, node);
1300         }
1301
1302         /* Reset queue */
1303         _queue_init(&surface_queue->free_queue);
1304         _queue_init(&surface_queue->dirty_queue);
1305         LIST_INITHEAD(&surface_queue->list);
1306
1307         if (surface_queue->impl && surface_queue->impl->reset)
1308                 surface_queue->impl->reset(surface_queue);
1309
1310         pthread_mutex_unlock(&surface_queue->lock);
1311         pthread_cond_signal(&surface_queue->free_cond);
1312
1313         _tbm_surf_queue_mutex_unlock();
1314
1315         _notify_emit(surface_queue, &surface_queue->reset_noti);
1316
1317         return TBM_SURFACE_QUEUE_ERROR_NONE;
1318 }
1319
1320 tbm_surface_queue_error_e
1321 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1322                         tbm_surface_h *surfaces, int *num)
1323 {
1324         queue_node *node = NULL;
1325         queue_node *tmp = NULL;
1326
1327         _tbm_surf_queue_mutex_lock();
1328
1329         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1330                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1331         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1332                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1333
1334         pthread_mutex_lock(&surface_queue->lock);
1335
1336         *num = 0;
1337         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1338                 if (surfaces)
1339                         surfaces[*num] = node->surface;
1340
1341                 *num = *num + 1;
1342         }
1343
1344         pthread_mutex_unlock(&surface_queue->lock);
1345
1346         _tbm_surf_queue_mutex_unlock();
1347
1348         return TBM_SURFACE_QUEUE_ERROR_NONE;
1349 }
1350
1351 typedef struct {
1352         int queue_size;
1353         int num_attached;
1354         int flags;
1355 } tbm_queue_default;
1356
1357 static void
1358 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1359 {
1360         tbm_queue_default *data = surface_queue->impl_data;
1361
1362         data->num_attached = 0;
1363 }
1364
1365 static void
1366 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1367 {
1368         tbm_queue_default *data = surface_queue->impl_data;
1369
1370         data->num_attached = 0;
1371 }
1372
1373 static void
1374 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1375 {
1376         free(surface_queue->impl_data);
1377 }
1378
1379 static void
1380 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1381 {
1382         tbm_queue_default *data = surface_queue->impl_data;
1383         tbm_surface_h surface;
1384
1385         if (data->queue_size == data->num_attached)
1386                 return;
1387
1388         if (surface_queue->alloc_cb) {
1389                 _tbm_surf_queue_mutex_unlock();
1390                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1391                 _tbm_surf_queue_mutex_lock();
1392
1393                 if (!surface)
1394                         return;
1395
1396                 tbm_surface_internal_ref(surface);
1397         } else {
1398                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1399                                 surface_queue->height,
1400                                 surface_queue->format,
1401                                 data->flags);
1402                 TBM_RETURN_IF_FAIL(surface != NULL);
1403         }
1404
1405         _tbm_surface_queue_attach(surface_queue, surface);
1406         tbm_surface_internal_unref(surface);
1407         data->num_attached++;
1408 }
1409
1410 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1411         __tbm_queue_default_init,
1412         __tbm_queue_default_reset,
1413         __tbm_queue_default_destroy,
1414         __tbm_queue_default_need_attach,
1415         NULL,                           /*__tbm_queue_default_enqueue*/
1416         NULL,                           /*__tbm_queue_default_release*/
1417         NULL,                           /*__tbm_queue_default_dequeue*/
1418         NULL,                           /*__tbm_queue_default_acquire*/
1419 };
1420
1421 tbm_surface_queue_h
1422 tbm_surface_queue_create(int queue_size, int width,
1423                          int height, int format, int flags)
1424 {
1425         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1426         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1427         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1428         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1429
1430         _tbm_surf_queue_mutex_lock();
1431
1432         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1433                                             sizeof(struct _tbm_surface_queue));
1434         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1435
1436         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1437
1438         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1439                                   sizeof(tbm_queue_default));
1440         if (data == NULL) {
1441                 free(surface_queue);
1442                 _tbm_surf_queue_mutex_unlock();
1443                 return NULL;
1444         }
1445
1446         data->queue_size = queue_size;
1447         data->flags = flags;
1448         _tbm_surface_queue_init(surface_queue,
1449                                 data->queue_size,
1450                                 width, height, format,
1451                                 &tbm_queue_default_impl, data);
1452
1453         _tbm_surf_queue_mutex_unlock();
1454
1455         return surface_queue;
1456 }
1457
1458 typedef struct {
1459         int queue_size;
1460         int num_attached;
1461         int flags;
1462         queue dequeue_list;
1463 } tbm_queue_sequence;
1464
1465 static void
1466 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1467 {
1468         tbm_queue_sequence *data = surface_queue->impl_data;
1469
1470         data->num_attached = 0;
1471         _queue_init(&data->dequeue_list);
1472 }
1473
1474 static void
1475 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1476 {
1477         tbm_queue_sequence *data = surface_queue->impl_data;
1478
1479         data->num_attached = 0;
1480         _queue_init(&data->dequeue_list);
1481 }
1482
1483 static void
1484 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1485 {
1486         free(surface_queue->impl_data);
1487 }
1488
1489 static void
1490 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1491 {
1492         tbm_queue_sequence *data = surface_queue->impl_data;
1493         tbm_surface_h surface;
1494
1495         if (data->queue_size == data->num_attached)
1496                 return;
1497
1498         if (surface_queue->alloc_cb) {
1499                 _tbm_surf_queue_mutex_unlock();
1500                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1501                 _tbm_surf_queue_mutex_lock();
1502
1503                 if (!surface)
1504                         return;
1505
1506                 tbm_surface_internal_ref(surface);
1507         } else {
1508                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1509                                 surface_queue->height,
1510                                 surface_queue->format,
1511                                 data->flags);
1512                 TBM_RETURN_IF_FAIL(surface != NULL);
1513         }
1514
1515         _tbm_surface_queue_attach(surface_queue, surface);
1516         tbm_surface_internal_unref(surface);
1517         data->num_attached++;
1518 }
1519
1520 static void
1521 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1522                              queue_node *node)
1523 {
1524         tbm_queue_sequence *data = surface_queue->impl_data;
1525         queue_node *next = NULL;
1526         queue_node *tmp = NULL;
1527
1528         node->priv_flags = 0;
1529
1530         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1531                 if (next->priv_flags)
1532                         break;
1533                 _queue_node_pop(&data->dequeue_list, next);
1534                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1535         }
1536 }
1537
1538 static queue_node *
1539 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1540                              surface_queue)
1541 {
1542         tbm_queue_sequence *data = surface_queue->impl_data;
1543         queue_node *node = NULL;
1544
1545         node = _tbm_surface_queue_dequeue(surface_queue);
1546         if (node) {
1547                 _queue_node_push_back(&data->dequeue_list, node);
1548                 node->priv_flags = 1;
1549         }
1550
1551         return node;
1552 }
1553
1554 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1555         __tbm_queue_sequence_init,
1556         __tbm_queue_sequence_reset,
1557         __tbm_queue_sequence_destroy,
1558         __tbm_queue_sequence_need_attach,
1559         __tbm_queue_sequence_enqueue,
1560         NULL,                                   /*__tbm_queue_sequence_release*/
1561         __tbm_queue_sequence_dequeue,
1562         NULL,                                   /*__tbm_queue_sequence_acquire*/
1563 };
1564
1565 tbm_surface_queue_h
1566 tbm_surface_queue_sequence_create(int queue_size, int width,
1567                                   int height, int format, int flags)
1568 {
1569         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1570         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1571         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1572         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1573
1574         _tbm_surf_queue_mutex_lock();
1575
1576         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1577                                             sizeof(struct _tbm_surface_queue));
1578         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1579
1580         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1581
1582         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1583                                    sizeof(tbm_queue_sequence));
1584         if (data == NULL) {
1585                 free(surface_queue);
1586                 return NULL;
1587         }
1588
1589         data->queue_size = queue_size;
1590         data->flags = flags;
1591         _tbm_surface_queue_init(surface_queue,
1592                                 data->queue_size,
1593                                 width, height, format,
1594                                 &tbm_queue_sequence_impl, data);
1595
1596         _tbm_surf_queue_mutex_unlock();
1597
1598         return surface_queue;
1599 }
1600 /* LCOV_EXCL_STOP */