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