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