tbm_surface_queue: change return code in tbm_surface_queue_release()
[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         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->dequeuable_noti);
548         LIST_INITHEAD(&surface_queue->dequeue_noti);
549         LIST_INITHEAD(&surface_queue->acquirable_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;
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 is existed in free_queue or dirty_queue node:%p, type:%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;
948
949         _tbm_surf_queue_mutex_lock();
950
951         *surface = NULL;
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 || node->surface == NULL) {
966                 TBM_LOG_E("_queue_node_pop_front failed\n");
967                 pthread_mutex_unlock(&surface_queue->lock);
968
969                 _tbm_surf_queue_mutex_unlock();
970                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
971         }
972
973         node->type = QUEUE_NODE_TYPE_DEQUEUE;
974         *surface = node->surface;
975
976         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
977
978         pthread_mutex_unlock(&surface_queue->lock);
979
980         _tbm_surf_queue_mutex_unlock();
981
982         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
983
984         return TBM_SURFACE_QUEUE_ERROR_NONE;
985 }
986
987 int
988 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
989 {
990         _tbm_surf_queue_mutex_lock();
991
992         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
993
994         pthread_mutex_lock(&surface_queue->lock);
995
996         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
997
998         if (_queue_is_empty(&surface_queue->free_queue)) {
999                 if (surface_queue->impl && surface_queue->impl->need_attach)
1000                         surface_queue->impl->need_attach(surface_queue);
1001
1002                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1003                                 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1004                                 _tbm_surf_queue_mutex_unlock();
1005                                 return 0;
1006                 }
1007         }
1008
1009         if (_queue_is_empty(&surface_queue->free_queue)) {
1010                 if (wait &&
1011                         _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) {
1012
1013                         _tbm_surf_queue_mutex_unlock();
1014
1015                         pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1016
1017                         _tbm_surf_queue_mutex_lock();
1018
1019                         if (!_tbm_surface_queue_is_valid(surface_queue)) {
1020                                   TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1021                                   _tbm_surf_queue_mutex_unlock();
1022                                   return 0;
1023                         }
1024
1025                         pthread_mutex_unlock(&surface_queue->lock);
1026
1027                         _tbm_surf_queue_mutex_unlock();
1028                         return 1;
1029                 }
1030
1031                 pthread_mutex_unlock(&surface_queue->lock);
1032
1033                 _tbm_surf_queue_mutex_unlock();
1034                 return 0;
1035         }
1036
1037         pthread_mutex_unlock(&surface_queue->lock);
1038
1039         _tbm_surf_queue_mutex_unlock();
1040
1041         return 1;
1042 }
1043
1044 tbm_surface_queue_error_e
1045 tbm_surface_queue_release(tbm_surface_queue_h
1046                           surface_queue, tbm_surface_h surface)
1047 {
1048         queue_node *node;
1049         int queue_type;
1050
1051         _tbm_surf_queue_mutex_lock();
1052
1053         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1054                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1055         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1056                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1057
1058         pthread_mutex_lock(&surface_queue->lock);
1059
1060         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1061
1062         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1063         if (node == NULL || queue_type != NODE_LIST) {
1064                 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1065                         node, queue_type);
1066                 pthread_mutex_unlock(&surface_queue->lock);
1067
1068                 _tbm_surf_queue_mutex_unlock();
1069                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1070         }
1071
1072         if (surface_queue->queue_size < surface_queue->num_attached) {
1073                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1074
1075                 if (surface_queue->impl && surface_queue->impl->need_detach)
1076                         surface_queue->impl->need_detach(surface_queue, node);
1077                 else
1078                         _tbm_surface_queue_detach(surface_queue, surface);
1079
1080                 pthread_mutex_unlock(&surface_queue->lock);
1081
1082                 _tbm_surf_queue_mutex_unlock();
1083                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1084         }
1085
1086         if (surface_queue->impl && surface_queue->impl->release)
1087                 surface_queue->impl->release(surface_queue, node);
1088         else
1089                 _tbm_surface_queue_release(surface_queue, node, 1);
1090
1091         if (_queue_is_empty(&surface_queue->free_queue)) {
1092                 pthread_mutex_unlock(&surface_queue->lock);
1093
1094                 _tbm_surf_queue_mutex_unlock();
1095                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1096         }
1097
1098         node->type = QUEUE_NODE_TYPE_RELEASE;
1099
1100         pthread_mutex_unlock(&surface_queue->lock);
1101         pthread_cond_signal(&surface_queue->free_cond);
1102
1103         _tbm_surf_queue_mutex_unlock();
1104
1105         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1106
1107         return TBM_SURFACE_QUEUE_ERROR_NONE;
1108 }
1109
1110 tbm_surface_queue_error_e
1111 tbm_surface_queue_acquire(tbm_surface_queue_h
1112                           surface_queue, tbm_surface_h *surface)
1113 {
1114         queue_node *node;
1115
1116         _tbm_surf_queue_mutex_lock();
1117
1118         *surface = NULL;
1119
1120         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1121                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1122         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1123                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1124
1125         pthread_mutex_lock(&surface_queue->lock);
1126
1127         if (surface_queue->impl && surface_queue->impl->acquire)
1128                 node = surface_queue->impl->acquire(surface_queue);
1129         else
1130                 node = _tbm_surface_queue_acquire(surface_queue);
1131
1132         if (node == NULL || node->surface == NULL) {
1133                 TBM_LOG_E("_queue_node_pop_front failed\n");
1134                 pthread_mutex_unlock(&surface_queue->lock);
1135
1136                 _tbm_surf_queue_mutex_unlock();
1137                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1138         }
1139
1140         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1141
1142         *surface = node->surface;
1143
1144         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1145
1146         pthread_mutex_unlock(&surface_queue->lock);
1147
1148         _tbm_surf_queue_mutex_unlock();
1149
1150         if (b_dump_queue)
1151                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1152
1153         return TBM_SURFACE_QUEUE_ERROR_NONE;
1154 }
1155
1156 int
1157 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1158 {
1159         _tbm_surf_queue_mutex_lock();
1160
1161         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1162
1163         pthread_mutex_lock(&surface_queue->lock);
1164
1165         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1166
1167         if (_queue_is_empty(&surface_queue->dirty_queue)) {
1168                 if (wait &&
1169                         _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
1170
1171                         _tbm_surf_queue_mutex_unlock();
1172
1173                         pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1174
1175                         _tbm_surf_queue_mutex_lock();
1176
1177                         if (!_tbm_surface_queue_is_valid(surface_queue)) {
1178                                   TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1179                                   _tbm_surf_queue_mutex_unlock();
1180                                   return 0;
1181                         }
1182
1183                         pthread_mutex_unlock(&surface_queue->lock);
1184
1185                         _tbm_surf_queue_mutex_unlock();
1186                         return 1;
1187                 }
1188
1189                 pthread_mutex_unlock(&surface_queue->lock);
1190
1191                 _tbm_surf_queue_mutex_unlock();
1192                 return 0;
1193         }
1194
1195         pthread_mutex_unlock(&surface_queue->lock);
1196
1197         _tbm_surf_queue_mutex_unlock();
1198
1199         return 1;
1200 }
1201
1202 void
1203 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1204 {
1205         queue_node *node, *tmp;
1206
1207         _tbm_surf_queue_mutex_lock();
1208
1209         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1210
1211         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1212
1213         LIST_DEL(&surface_queue->item_link);
1214
1215         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1216                 _queue_delete_node(surface_queue, node);
1217
1218         if (surface_queue->impl && surface_queue->impl->destroy)
1219                 surface_queue->impl->destroy(surface_queue);
1220
1221         _notify_emit(surface_queue, &surface_queue->destory_noti);
1222
1223         _notify_remove_all(&surface_queue->destory_noti);
1224         _notify_remove_all(&surface_queue->dequeuable_noti);
1225         _notify_remove_all(&surface_queue->dequeue_noti);
1226         _notify_remove_all(&surface_queue->acquirable_noti);
1227         _notify_remove_all(&surface_queue->reset_noti);
1228
1229         pthread_mutex_destroy(&surface_queue->lock);
1230
1231         free(surface_queue);
1232
1233         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1234                 _deinit_tbm_surf_queue_bufmgr();
1235
1236         _tbm_surf_queue_mutex_unlock();
1237 }
1238
1239 tbm_surface_queue_error_e
1240 tbm_surface_queue_reset(tbm_surface_queue_h
1241                         surface_queue, int width, int height, int format)
1242 {
1243         queue_node *node, *tmp;
1244
1245         _tbm_surf_queue_mutex_lock();
1246
1247         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1248                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1249
1250         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1251
1252         if (width == surface_queue->width && height == surface_queue->height &&
1253                 format == surface_queue->format) {
1254                 _tbm_surf_queue_mutex_unlock();
1255                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1256         }
1257
1258         pthread_mutex_lock(&surface_queue->lock);
1259
1260         surface_queue->width = width;
1261         surface_queue->height = height;
1262         surface_queue->format = format;
1263
1264         /* Destory surface and Push to free_queue */
1265         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1266                 _queue_delete_node(surface_queue, node);
1267
1268         /* Reset queue */
1269         _queue_init(&surface_queue->free_queue);
1270         _queue_init(&surface_queue->dirty_queue);
1271         LIST_INITHEAD(&surface_queue->list);
1272
1273         surface_queue->num_attached = 0;
1274
1275         if (surface_queue->impl && surface_queue->impl->reset)
1276                 surface_queue->impl->reset(surface_queue);
1277
1278         pthread_mutex_unlock(&surface_queue->lock);
1279         pthread_cond_signal(&surface_queue->free_cond);
1280
1281         _tbm_surf_queue_mutex_unlock();
1282
1283         _notify_emit(surface_queue, &surface_queue->reset_noti);
1284
1285         return TBM_SURFACE_QUEUE_ERROR_NONE;
1286 }
1287
1288 tbm_surface_queue_error_e
1289 tbm_surface_queue_set_size(tbm_surface_queue_h
1290                         surface_queue, int queue_size, int flush)
1291 {
1292         queue_node *node, *tmp;
1293
1294         _tbm_surf_queue_mutex_lock();
1295
1296         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1297                                         TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1298         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1299                                         TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1300
1301         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1302
1303         if ((surface_queue->queue_size == queue_size) && !flush) {
1304                 _tbm_surf_queue_mutex_unlock();
1305                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1306         }
1307
1308         pthread_mutex_lock(&surface_queue->lock);
1309
1310         if (flush) {
1311                 /* Destory surface and Push to free_queue */
1312                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1313                         _queue_delete_node(surface_queue, node);
1314
1315                 /* Reset queue */
1316                 _queue_init(&surface_queue->free_queue);
1317                 _queue_init(&surface_queue->dirty_queue);
1318                 LIST_INITHEAD(&surface_queue->list);
1319
1320                 surface_queue->num_attached = 0;
1321                 surface_queue->queue_size = queue_size;
1322
1323                 if (surface_queue->impl && surface_queue->impl->reset)
1324                         surface_queue->impl->reset(surface_queue);
1325
1326                 pthread_mutex_unlock(&surface_queue->lock);
1327                 pthread_cond_signal(&surface_queue->free_cond);
1328
1329                 _tbm_surf_queue_mutex_unlock();
1330
1331                 _notify_emit(surface_queue, &surface_queue->reset_noti);
1332
1333                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1334         } else {
1335                 if (surface_queue->queue_size > queue_size) {
1336                         int need_del = surface_queue->queue_size - queue_size;
1337
1338                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1339                                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1340
1341                                 if (surface_queue->impl && surface_queue->impl->need_detach)
1342                                         surface_queue->impl->need_detach(surface_queue, node);
1343                                 else
1344                                         _tbm_surface_queue_detach(surface_queue, node->surface);
1345
1346                                 need_del--;
1347                                 if (need_del == 0)
1348                                         break;
1349                         }
1350                 }
1351
1352                 surface_queue->queue_size = queue_size;
1353
1354                 pthread_mutex_unlock(&surface_queue->lock);
1355
1356                 _tbm_surf_queue_mutex_unlock();
1357
1358                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1359         }
1360 }
1361
1362 tbm_surface_queue_error_e
1363 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1364 {
1365         queue_node *node, *tmp;
1366
1367         _tbm_surf_queue_mutex_lock();
1368
1369         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1370                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1371
1372         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1373
1374         if (surface_queue->num_attached == 0) {
1375                 _tbm_surf_queue_mutex_unlock();
1376                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1377         }
1378
1379         pthread_mutex_lock(&surface_queue->lock);
1380
1381         /* Destory surface and Push to free_queue */
1382         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1383                 _queue_delete_node(surface_queue, node);
1384
1385         /* Reset queue */
1386         _queue_init(&surface_queue->free_queue);
1387         _queue_init(&surface_queue->dirty_queue);
1388         LIST_INITHEAD(&surface_queue->list);
1389
1390         surface_queue->num_attached = 0;
1391
1392         if (surface_queue->impl && surface_queue->impl->reset)
1393                 surface_queue->impl->reset(surface_queue);
1394
1395         pthread_mutex_unlock(&surface_queue->lock);
1396         pthread_cond_signal(&surface_queue->free_cond);
1397
1398         _tbm_surf_queue_mutex_unlock();
1399
1400         _notify_emit(surface_queue, &surface_queue->reset_noti);
1401
1402         return TBM_SURFACE_QUEUE_ERROR_NONE;
1403 }
1404
1405 tbm_surface_queue_error_e
1406 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1407                         tbm_surface_h *surfaces, int *num)
1408 {
1409         queue_node *node;
1410
1411         _tbm_surf_queue_mutex_lock();
1412
1413         *num = 0;
1414
1415         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1416                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1417         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1418                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1419
1420         pthread_mutex_lock(&surface_queue->lock);
1421
1422         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1423                 if (surfaces)
1424                         surfaces[*num] = node->surface;
1425
1426                 *num = *num + 1;
1427         }
1428
1429         pthread_mutex_unlock(&surface_queue->lock);
1430
1431         _tbm_surf_queue_mutex_unlock();
1432
1433         return TBM_SURFACE_QUEUE_ERROR_NONE;
1434 }
1435
1436 typedef struct {
1437         int flags;
1438 } tbm_queue_default;
1439
1440 static void
1441 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1442 {
1443         free(surface_queue->impl_data);
1444 }
1445
1446 static void
1447 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1448 {
1449         tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1450         tbm_surface_h surface;
1451
1452         if (surface_queue->queue_size == surface_queue->num_attached)
1453                 return;
1454
1455         if (surface_queue->alloc_cb) {
1456                 _tbm_surf_queue_mutex_unlock();
1457                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1458                 _tbm_surf_queue_mutex_lock();
1459
1460                 if (!surface)
1461                         return;
1462
1463                 tbm_surface_internal_ref(surface);
1464         } else {
1465                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1466                                 surface_queue->height,
1467                                 surface_queue->format,
1468                                 data->flags);
1469                 TBM_RETURN_IF_FAIL(surface != NULL);
1470         }
1471
1472         _tbm_surface_queue_attach(surface_queue, surface);
1473         tbm_surface_internal_unref(surface);
1474 }
1475
1476 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1477         NULL,                           /*__tbm_queue_default_init*/
1478         NULL,                           /*__tbm_queue_default_reset*/
1479         __tbm_queue_default_destroy,
1480         __tbm_queue_default_need_attach,
1481         NULL,                           /*__tbm_queue_default_enqueue*/
1482         NULL,                           /*__tbm_queue_default_release*/
1483         NULL,                           /*__tbm_queue_default_dequeue*/
1484         NULL,                           /*__tbm_queue_default_acquire*/
1485         NULL,                           /*__tbm_queue_default_need_detach*/
1486 };
1487
1488 tbm_surface_queue_h
1489 tbm_surface_queue_create(int queue_size, int width,
1490                          int height, int format, int flags)
1491 {
1492         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1493         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1494         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1495         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1496
1497         _tbm_surf_queue_mutex_lock();
1498
1499         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1500                                             sizeof(struct _tbm_surface_queue));
1501         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1502
1503         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1504
1505         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1506                                   sizeof(tbm_queue_default));
1507         if (data == NULL) {
1508                 free(surface_queue);
1509                 _tbm_surf_queue_mutex_unlock();
1510                 return NULL;
1511         }
1512
1513         data->flags = flags;
1514         _tbm_surface_queue_init(surface_queue,
1515                                 queue_size,
1516                                 width, height, format,
1517                                 &tbm_queue_default_impl, data);
1518
1519         _tbm_surf_queue_mutex_unlock();
1520
1521         return surface_queue;
1522 }
1523
1524 typedef struct {
1525         int flags;
1526         queue dequeue_list;
1527 } tbm_queue_sequence;
1528
1529 static void
1530 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1531 {
1532         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1533
1534         _queue_init(&data->dequeue_list);
1535 }
1536
1537 static void
1538 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1539 {
1540         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1541
1542         _queue_init(&data->dequeue_list);
1543 }
1544
1545 static void
1546 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1547 {
1548         free(surface_queue->impl_data);
1549 }
1550
1551 static void
1552 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1553 {
1554         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1555         tbm_surface_h surface;
1556
1557         if (surface_queue->queue_size == surface_queue->num_attached)
1558                 return;
1559
1560         if (surface_queue->alloc_cb) {
1561                 _tbm_surf_queue_mutex_unlock();
1562                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1563                 _tbm_surf_queue_mutex_lock();
1564
1565                 if (!surface)
1566                         return;
1567
1568                 tbm_surface_internal_ref(surface);
1569         } else {
1570                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1571                                 surface_queue->height,
1572                                 surface_queue->format,
1573                                 data->flags);
1574                 TBM_RETURN_IF_FAIL(surface != NULL);
1575         }
1576
1577         _tbm_surface_queue_attach(surface_queue, surface);
1578         tbm_surface_internal_unref(surface);
1579 }
1580
1581 static void
1582 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1583                              queue_node *node)
1584 {
1585         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1586         queue_node *next, *tmp;
1587
1588         node->priv_flags = 0;
1589
1590         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1591                 if (next->priv_flags)
1592                         break;
1593                 _queue_node_pop(&data->dequeue_list, next);
1594                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1595         }
1596 }
1597
1598 static queue_node *
1599 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1600                              surface_queue)
1601 {
1602         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1603         queue_node *node;
1604
1605         node = _tbm_surface_queue_dequeue(surface_queue);
1606         if (node) {
1607                 _queue_node_push_back(&data->dequeue_list, node);
1608                 node->priv_flags = 1;
1609         }
1610
1611         return node;
1612 }
1613
1614 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1615         __tbm_queue_sequence_init,
1616         __tbm_queue_sequence_reset,
1617         __tbm_queue_sequence_destroy,
1618         __tbm_queue_sequence_need_attach,
1619         __tbm_queue_sequence_enqueue,
1620         NULL,                                   /*__tbm_queue_sequence_release*/
1621         __tbm_queue_sequence_dequeue,
1622         NULL,                                   /*__tbm_queue_sequence_acquire*/
1623         NULL,                                   /*__tbm_queue_sequence_need_dettach*/
1624 };
1625
1626 tbm_surface_queue_h
1627 tbm_surface_queue_sequence_create(int queue_size, int width,
1628                                   int height, int format, int flags)
1629 {
1630         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1631         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1632         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1633         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1634
1635         _tbm_surf_queue_mutex_lock();
1636
1637         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1638                                             sizeof(struct _tbm_surface_queue));
1639         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1640
1641         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1642
1643         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1644                                    sizeof(tbm_queue_sequence));
1645         if (data == NULL) {
1646                 free(surface_queue);
1647                 _tbm_surf_queue_mutex_unlock();
1648                 return NULL;
1649         }
1650
1651         data->flags = flags;
1652         _tbm_surface_queue_init(surface_queue,
1653                                 queue_size,
1654                                 width, height, format,
1655                                 &tbm_queue_sequence_impl, data);
1656
1657         _tbm_surf_queue_mutex_unlock();
1658
1659         return surface_queue;
1660 }
1661 /* LCOV_EXCL_STOP */