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