b4dfaec8768128ef8a7db5f1cfbab85c3141c456
[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         if (_queue_is_empty(&surface_queue->free_queue)) {
571                 if (surface_queue->impl && surface_queue->impl->need_attach)
572                         surface_queue->impl->need_attach(surface_queue);
573
574                 if (_queue_is_empty(&surface_queue->free_queue)) {
575                         TBM_LOG_E("surface_queue->free_queue is empty.\n");
576                         return NULL;
577                 }
578         }
579
580         node = _queue_node_pop_front(&surface_queue->free_queue);
581
582         return node;
583 }
584
585 static queue_node *
586 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
587 {
588         queue_node *node;
589
590         if (_queue_is_empty(&surface_queue->dirty_queue))
591                 return NULL;
592
593         node = _queue_node_pop_front(&surface_queue->dirty_queue);
594
595         return node;
596 }
597
598 static void
599 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
600                            queue_node *node, int push_back)
601 {
602         if (push_back)
603                 _queue_node_push_back(&surface_queue->free_queue, node);
604         else
605                 _queue_node_push_front(&surface_queue->free_queue, node);
606 }
607
608 static void
609 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
610                         int queue_size,
611                         int width, int height, int format,
612                         const tbm_surface_queue_interface *impl, void *data)
613 {
614         TBM_RETURN_IF_FAIL(surface_queue != NULL);
615         TBM_RETURN_IF_FAIL(impl != NULL);
616
617         if (!g_surf_queue_bufmgr)
618                 _init_tbm_surf_queue_bufmgr();
619
620         pthread_mutex_init(&surface_queue->lock, NULL);
621         pthread_cond_init(&surface_queue->free_cond, NULL);
622         pthread_cond_init(&surface_queue->dirty_cond, NULL);
623
624         surface_queue->queue_size = queue_size;
625         surface_queue->width = width;
626         surface_queue->height = height;
627         surface_queue->format = format;
628         surface_queue->impl = impl;
629         surface_queue->impl_data = data;
630
631         _queue_init(&surface_queue->free_queue);
632         _queue_init(&surface_queue->dirty_queue);
633         LIST_INITHEAD(&surface_queue->list);
634
635         LIST_INITHEAD(&surface_queue->destory_noti);
636         LIST_INITHEAD(&surface_queue->dequeuable_noti);
637         LIST_INITHEAD(&surface_queue->dequeue_noti);
638         LIST_INITHEAD(&surface_queue->can_dequeue_noti);
639         LIST_INITHEAD(&surface_queue->acquirable_noti);
640         LIST_INITHEAD(&surface_queue->reset_noti);
641         LIST_INITHEAD(&surface_queue->trace_noti);
642
643         if (surface_queue->impl && surface_queue->impl->init)
644                 surface_queue->impl->init(surface_queue);
645
646         LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
647 }
648
649 tbm_surface_queue_error_e
650 tbm_surface_queue_add_destroy_cb(
651         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
652         void *data)
653 {
654         _tbm_surf_queue_mutex_lock();
655
656         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
657                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
658
659         pthread_mutex_lock(&surface_queue->lock);
660
661         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
662
663         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
664
665         pthread_mutex_unlock(&surface_queue->lock);
666
667         _tbm_surf_queue_mutex_unlock();
668
669         return TBM_SURFACE_QUEUE_ERROR_NONE;
670 }
671
672 tbm_surface_queue_error_e
673 tbm_surface_queue_remove_destroy_cb(
674         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
675         void *data)
676 {
677         _tbm_surf_queue_mutex_lock();
678
679         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
680                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
681
682         pthread_mutex_lock(&surface_queue->lock);
683
684         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
685
686         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
687
688         pthread_mutex_unlock(&surface_queue->lock);
689
690         _tbm_surf_queue_mutex_unlock();
691
692         return TBM_SURFACE_QUEUE_ERROR_NONE;
693 }
694
695 tbm_surface_queue_error_e
696 tbm_surface_queue_add_dequeuable_cb(
697         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
698         void *data)
699 {
700         _tbm_surf_queue_mutex_lock();
701
702         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
703                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
704
705         pthread_mutex_lock(&surface_queue->lock);
706
707         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
708
709         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
710
711         pthread_mutex_unlock(&surface_queue->lock);
712
713         _tbm_surf_queue_mutex_unlock();
714
715         return TBM_SURFACE_QUEUE_ERROR_NONE;
716 }
717
718 tbm_surface_queue_error_e
719 tbm_surface_queue_remove_dequeuable_cb(
720         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
721         void *data)
722 {
723         _tbm_surf_queue_mutex_lock();
724
725         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
726                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
727
728         pthread_mutex_lock(&surface_queue->lock);
729
730         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
731
732         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
733
734         pthread_mutex_unlock(&surface_queue->lock);
735
736         _tbm_surf_queue_mutex_unlock();
737
738         return TBM_SURFACE_QUEUE_ERROR_NONE;
739 }
740
741 tbm_surface_queue_error_e
742 tbm_surface_queue_add_dequeue_cb(
743         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
744         void *data)
745 {
746         _tbm_surf_queue_mutex_lock();
747
748         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
749                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
750
751         pthread_mutex_lock(&surface_queue->lock);
752
753         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
754
755         _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
756
757         pthread_mutex_unlock(&surface_queue->lock);
758
759         _tbm_surf_queue_mutex_unlock();
760
761         return TBM_SURFACE_QUEUE_ERROR_NONE;
762 }
763
764 tbm_surface_queue_error_e
765 tbm_surface_queue_remove_dequeue_cb(
766         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
767         void *data)
768 {
769         _tbm_surf_queue_mutex_lock();
770
771         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
772                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
773
774         pthread_mutex_lock(&surface_queue->lock);
775
776         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
777
778         _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
779
780         pthread_mutex_unlock(&surface_queue->lock);
781
782         _tbm_surf_queue_mutex_unlock();
783
784         return TBM_SURFACE_QUEUE_ERROR_NONE;
785 }
786
787 tbm_surface_queue_error_e
788 tbm_surface_queue_add_can_dequeue_cb(
789         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
790         void *data)
791 {
792         _tbm_surf_queue_mutex_lock();
793
794         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
795                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
796
797         pthread_mutex_lock(&surface_queue->lock);
798
799         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
800
801         _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
802
803         pthread_mutex_unlock(&surface_queue->lock);
804
805         _tbm_surf_queue_mutex_unlock();
806
807         return TBM_SURFACE_QUEUE_ERROR_NONE;
808 }
809
810 tbm_surface_queue_error_e
811 tbm_surface_queue_remove_can_dequeue_cb(
812         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
813         void *data)
814 {
815         _tbm_surf_queue_mutex_lock();
816
817         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
818                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
819
820         pthread_mutex_lock(&surface_queue->lock);
821
822         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
823
824         _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
825
826         pthread_mutex_unlock(&surface_queue->lock);
827
828         _tbm_surf_queue_mutex_unlock();
829
830         return TBM_SURFACE_QUEUE_ERROR_NONE;
831 }
832
833 tbm_surface_queue_error_e
834 tbm_surface_queue_add_acquirable_cb(
835         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
836         void *data)
837 {
838         _tbm_surf_queue_mutex_lock();
839
840         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
841                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
842
843         pthread_mutex_lock(&surface_queue->lock);
844
845         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
846
847         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
848
849         pthread_mutex_unlock(&surface_queue->lock);
850
851         _tbm_surf_queue_mutex_unlock();
852
853         return TBM_SURFACE_QUEUE_ERROR_NONE;
854 }
855
856 tbm_surface_queue_error_e
857 tbm_surface_queue_remove_acquirable_cb(
858         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
859         void *data)
860 {
861         _tbm_surf_queue_mutex_lock();
862
863         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
864                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
865
866         pthread_mutex_lock(&surface_queue->lock);
867
868         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
869
870         _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
871
872         pthread_mutex_unlock(&surface_queue->lock);
873
874         _tbm_surf_queue_mutex_unlock();
875
876         return TBM_SURFACE_QUEUE_ERROR_NONE;
877 }
878
879 tbm_surface_queue_error_e
880 tbm_surface_queue_add_trace_cb(
881         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
882         void *data)
883 {
884         _tbm_surf_queue_mutex_lock();
885
886         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
887                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
888
889         pthread_mutex_lock(&surface_queue->lock);
890
891         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
892
893         _trace_add(&surface_queue->trace_noti, trace_cb, data);
894
895         pthread_mutex_unlock(&surface_queue->lock);
896
897         _tbm_surf_queue_mutex_unlock();
898
899         return TBM_SURFACE_QUEUE_ERROR_NONE;
900 }
901
902 tbm_surface_queue_error_e
903 tbm_surface_queue_remove_trace_cb(
904         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
905         void *data)
906 {
907         _tbm_surf_queue_mutex_lock();
908
909         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
910                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
911
912         pthread_mutex_lock(&surface_queue->lock);
913
914         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
915
916         _trace_remove(&surface_queue->trace_noti, trace_cb, data);
917
918         pthread_mutex_unlock(&surface_queue->lock);
919
920         _tbm_surf_queue_mutex_unlock();
921
922         return TBM_SURFACE_QUEUE_ERROR_NONE;
923 }
924
925 tbm_surface_queue_error_e
926 tbm_surface_queue_set_alloc_cb(
927         tbm_surface_queue_h surface_queue,
928         tbm_surface_alloc_cb alloc_cb,
929         tbm_surface_free_cb free_cb,
930         void *data)
931 {
932         _tbm_surf_queue_mutex_lock();
933
934         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
935                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
936
937         pthread_mutex_lock(&surface_queue->lock);
938
939         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
940
941         surface_queue->alloc_cb = alloc_cb;
942         surface_queue->free_cb = free_cb;
943         surface_queue->alloc_cb_data = data;
944
945         pthread_mutex_unlock(&surface_queue->lock);
946
947         _tbm_surf_queue_mutex_unlock();
948
949         return TBM_SURFACE_QUEUE_ERROR_NONE;
950 }
951
952 int
953 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
954 {
955         int width;
956
957         _tbm_surf_queue_mutex_lock();
958
959         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
960
961         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
962
963         width = surface_queue->width;
964
965         _tbm_surf_queue_mutex_unlock();
966
967         return width;
968 }
969
970 int
971 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
972 {
973         int height;
974
975         _tbm_surf_queue_mutex_lock();
976
977         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
978
979         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
980
981         height = surface_queue->height;
982
983         _tbm_surf_queue_mutex_unlock();
984
985         return height;
986 }
987
988 int
989 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
990 {
991         int format;
992
993         _tbm_surf_queue_mutex_lock();
994
995         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
996
997         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
998
999         format = surface_queue->format;
1000
1001         _tbm_surf_queue_mutex_unlock();
1002
1003         return format;
1004 }
1005
1006 int
1007 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1008 {
1009         int queue_size;
1010
1011         _tbm_surf_queue_mutex_lock();
1012
1013         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1014
1015         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1016
1017         queue_size = surface_queue->queue_size;
1018
1019         _tbm_surf_queue_mutex_unlock();
1020
1021         return queue_size;
1022 }
1023
1024 tbm_surface_queue_error_e
1025 tbm_surface_queue_add_reset_cb(
1026         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1027         void *data)
1028 {
1029         _tbm_surf_queue_mutex_lock();
1030
1031         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1032                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1033
1034         pthread_mutex_lock(&surface_queue->lock);
1035
1036         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1037
1038         _notify_add(&surface_queue->reset_noti, reset_cb, data);
1039
1040         pthread_mutex_unlock(&surface_queue->lock);
1041
1042         _tbm_surf_queue_mutex_unlock();
1043
1044         return TBM_SURFACE_QUEUE_ERROR_NONE;
1045 }
1046
1047 tbm_surface_queue_error_e
1048 tbm_surface_queue_remove_reset_cb(
1049         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1050         void *data)
1051 {
1052         _tbm_surf_queue_mutex_lock();
1053
1054         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1055                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1056
1057         pthread_mutex_lock(&surface_queue->lock);
1058
1059         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1060
1061         _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1062
1063         pthread_mutex_unlock(&surface_queue->lock);
1064
1065         _tbm_surf_queue_mutex_unlock();
1066
1067         return TBM_SURFACE_QUEUE_ERROR_NONE;
1068 }
1069
1070 tbm_surface_queue_error_e
1071 tbm_surface_queue_enqueue(tbm_surface_queue_h
1072                           surface_queue, tbm_surface_h surface)
1073 {
1074         queue_node *node;
1075         int queue_type;
1076
1077         _tbm_surf_queue_mutex_lock();
1078
1079         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1080                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1081         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1082                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1083
1084         if (b_dump_queue)
1085                 tbm_surface_internal_dump_buffer(surface, "enqueue");
1086
1087         pthread_mutex_lock(&surface_queue->lock);
1088
1089         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1090
1091         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1092         if (node == NULL || queue_type != NODE_LIST) {
1093                 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1094                         node, queue_type);
1095                 pthread_mutex_unlock(&surface_queue->lock);
1096
1097                 _tbm_surf_queue_mutex_unlock();
1098                 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1099         }
1100
1101         if (surface_queue->impl && surface_queue->impl->enqueue)
1102                 surface_queue->impl->enqueue(surface_queue, node);
1103         else
1104                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1105
1106         if (_queue_is_empty(&surface_queue->dirty_queue)) {
1107                 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1108                 pthread_mutex_unlock(&surface_queue->lock);
1109
1110                 _tbm_surf_queue_mutex_unlock();
1111                 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1112         }
1113
1114         node->type = QUEUE_NODE_TYPE_ENQUEUE;
1115
1116         pthread_mutex_unlock(&surface_queue->lock);
1117         pthread_cond_signal(&surface_queue->dirty_cond);
1118
1119         _tbm_surf_queue_mutex_unlock();
1120
1121         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1122
1123         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1124
1125         return TBM_SURFACE_QUEUE_ERROR_NONE;
1126 }
1127
1128 tbm_surface_queue_error_e
1129 tbm_surface_queue_dequeue(tbm_surface_queue_h
1130                           surface_queue, tbm_surface_h *surface)
1131 {
1132         queue_node *node;
1133
1134         _tbm_surf_queue_mutex_lock();
1135
1136         *surface = NULL;
1137
1138         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1139                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1140         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1141                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1142
1143         pthread_mutex_lock(&surface_queue->lock);
1144
1145         if (surface_queue->impl && surface_queue->impl->dequeue)
1146                 node = surface_queue->impl->dequeue(surface_queue);
1147         else
1148                 node = _tbm_surface_queue_dequeue(surface_queue);
1149
1150         if (node == NULL || node->surface == NULL) {
1151                 TBM_LOG_E("_queue_node_pop_front failed\n");
1152                 pthread_mutex_unlock(&surface_queue->lock);
1153
1154                 _tbm_surf_queue_mutex_unlock();
1155                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1156         }
1157
1158         node->type = QUEUE_NODE_TYPE_DEQUEUE;
1159         *surface = node->surface;
1160
1161         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1162
1163         pthread_mutex_unlock(&surface_queue->lock);
1164
1165         _tbm_surf_queue_mutex_unlock();
1166
1167         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1168
1169         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1170
1171         return TBM_SURFACE_QUEUE_ERROR_NONE;
1172 }
1173
1174 int
1175 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1176 {
1177         _tbm_surf_queue_mutex_lock();
1178
1179         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1180
1181         _tbm_surf_queue_mutex_unlock();
1182
1183         _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1184
1185         _tbm_surf_queue_mutex_lock();
1186
1187         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1188
1189         pthread_mutex_lock(&surface_queue->lock);
1190
1191         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1192
1193         if (_queue_is_empty(&surface_queue->free_queue)) {
1194                 if (surface_queue->impl && surface_queue->impl->need_attach)
1195                         surface_queue->impl->need_attach(surface_queue);
1196
1197                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1198                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1199                         pthread_mutex_unlock(&surface_queue->lock);
1200                         _tbm_surf_queue_mutex_unlock();
1201                         return 0;
1202                 }
1203         }
1204
1205         if (!_queue_is_empty(&surface_queue->free_queue)) {
1206                 pthread_mutex_unlock(&surface_queue->lock);
1207                 _tbm_surf_queue_mutex_unlock();
1208                 return 1;
1209         }
1210
1211         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1212                                                 QUEUE_NODE_TYPE_ACQUIRE)) {
1213                 _tbm_surf_queue_mutex_unlock();
1214                 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1215                 _tbm_surf_queue_mutex_lock();
1216
1217                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1218                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1219                         pthread_mutex_unlock(&surface_queue->lock);
1220                         _tbm_surf_queue_mutex_unlock();
1221                         return 0;
1222                 }
1223
1224                 pthread_mutex_unlock(&surface_queue->lock);
1225                 _tbm_surf_queue_mutex_unlock();
1226                 return 1;
1227         }
1228
1229         pthread_mutex_unlock(&surface_queue->lock);
1230         _tbm_surf_queue_mutex_unlock();
1231         return 0;
1232 }
1233
1234 tbm_surface_queue_error_e
1235 tbm_surface_queue_release(tbm_surface_queue_h
1236                           surface_queue, tbm_surface_h surface)
1237 {
1238         queue_node *node;
1239         int queue_type;
1240
1241         _tbm_surf_queue_mutex_lock();
1242
1243         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1244                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1245         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1246                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1247
1248         pthread_mutex_lock(&surface_queue->lock);
1249
1250         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1251
1252         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1253         if (node == NULL || queue_type != NODE_LIST) {
1254                 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1255                         node, queue_type);
1256                 pthread_mutex_unlock(&surface_queue->lock);
1257
1258                 _tbm_surf_queue_mutex_unlock();
1259                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1260         }
1261
1262         if (surface_queue->queue_size < surface_queue->num_attached) {
1263                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1264
1265                 if (surface_queue->impl && surface_queue->impl->need_detach)
1266                         surface_queue->impl->need_detach(surface_queue, node);
1267                 else
1268                         _tbm_surface_queue_detach(surface_queue, surface);
1269
1270                 pthread_mutex_unlock(&surface_queue->lock);
1271
1272                 _tbm_surf_queue_mutex_unlock();
1273                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1274         }
1275
1276         if (surface_queue->impl && surface_queue->impl->release)
1277                 surface_queue->impl->release(surface_queue, node);
1278         else
1279                 _tbm_surface_queue_release(surface_queue, node, 1);
1280
1281         if (_queue_is_empty(&surface_queue->free_queue)) {
1282                 pthread_mutex_unlock(&surface_queue->lock);
1283
1284                 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1285                 _tbm_surf_queue_mutex_unlock();
1286                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1287         }
1288
1289         node->type = QUEUE_NODE_TYPE_RELEASE;
1290
1291         pthread_mutex_unlock(&surface_queue->lock);
1292         pthread_cond_signal(&surface_queue->free_cond);
1293
1294         _tbm_surf_queue_mutex_unlock();
1295
1296         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1297
1298         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1299
1300         return TBM_SURFACE_QUEUE_ERROR_NONE;
1301 }
1302
1303 tbm_surface_queue_error_e
1304 tbm_surface_queue_acquire(tbm_surface_queue_h
1305                           surface_queue, tbm_surface_h *surface)
1306 {
1307         queue_node *node;
1308
1309         _tbm_surf_queue_mutex_lock();
1310
1311         *surface = NULL;
1312
1313         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1314                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1315         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1316                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1317
1318         pthread_mutex_lock(&surface_queue->lock);
1319
1320         if (surface_queue->impl && surface_queue->impl->acquire)
1321                 node = surface_queue->impl->acquire(surface_queue);
1322         else
1323                 node = _tbm_surface_queue_acquire(surface_queue);
1324
1325         if (node == NULL || node->surface == NULL) {
1326                 TBM_LOG_E("_queue_node_pop_front failed\n");
1327                 pthread_mutex_unlock(&surface_queue->lock);
1328
1329                 _tbm_surf_queue_mutex_unlock();
1330                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1331         }
1332
1333         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1334
1335         *surface = node->surface;
1336
1337         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1338
1339         pthread_mutex_unlock(&surface_queue->lock);
1340
1341         _tbm_surf_queue_mutex_unlock();
1342
1343         if (b_dump_queue)
1344                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1345
1346         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1347
1348         return TBM_SURFACE_QUEUE_ERROR_NONE;
1349 }
1350
1351 int
1352 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1353 {
1354         _tbm_surf_queue_mutex_lock();
1355
1356         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1357
1358         pthread_mutex_lock(&surface_queue->lock);
1359
1360         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1361
1362         if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1363                 pthread_mutex_unlock(&surface_queue->lock);
1364                 _tbm_surf_queue_mutex_unlock();
1365                 return 1;
1366         }
1367
1368         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1369                                                 QUEUE_NODE_TYPE_DEQUEUE)) {
1370                 _tbm_surf_queue_mutex_unlock();
1371                 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1372                 _tbm_surf_queue_mutex_lock();
1373
1374                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1375                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1376                         pthread_mutex_unlock(&surface_queue->lock);
1377                         _tbm_surf_queue_mutex_unlock();
1378                         return 0;
1379                 }
1380
1381                 pthread_mutex_unlock(&surface_queue->lock);
1382                 _tbm_surf_queue_mutex_unlock();
1383                 return 1;
1384         }
1385
1386         pthread_mutex_unlock(&surface_queue->lock);
1387         _tbm_surf_queue_mutex_unlock();
1388         return 0;
1389 }
1390
1391 void
1392 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1393 {
1394         queue_node *node = NULL, *tmp;
1395
1396         _tbm_surf_queue_mutex_lock();
1397
1398         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1399
1400         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1401
1402         LIST_DEL(&surface_queue->item_link);
1403
1404         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1405                 _queue_delete_node(surface_queue, node);
1406
1407         if (surface_queue->impl && surface_queue->impl->destroy)
1408                 surface_queue->impl->destroy(surface_queue);
1409
1410         _notify_emit(surface_queue, &surface_queue->destory_noti);
1411
1412         _notify_remove_all(&surface_queue->destory_noti);
1413         _notify_remove_all(&surface_queue->dequeuable_noti);
1414         _notify_remove_all(&surface_queue->dequeue_noti);
1415         _notify_remove_all(&surface_queue->can_dequeue_noti);
1416         _notify_remove_all(&surface_queue->acquirable_noti);
1417         _notify_remove_all(&surface_queue->reset_noti);
1418         _trace_remove_all(&surface_queue->trace_noti);
1419
1420         pthread_mutex_destroy(&surface_queue->lock);
1421
1422         free(surface_queue);
1423
1424         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1425                 _deinit_tbm_surf_queue_bufmgr();
1426
1427         _tbm_surf_queue_mutex_unlock();
1428 }
1429
1430 tbm_surface_queue_error_e
1431 tbm_surface_queue_reset(tbm_surface_queue_h
1432                         surface_queue, int width, int height, int format)
1433 {
1434         queue_node *node = NULL, *tmp;
1435
1436         _tbm_surf_queue_mutex_lock();
1437
1438         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1439                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1440
1441         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1442
1443         if (width == surface_queue->width && height == surface_queue->height &&
1444                 format == surface_queue->format) {
1445                 _tbm_surf_queue_mutex_unlock();
1446                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1447         }
1448
1449         pthread_mutex_lock(&surface_queue->lock);
1450
1451         surface_queue->width = width;
1452         surface_queue->height = height;
1453         surface_queue->format = format;
1454
1455         /* Destory surface and Push to free_queue */
1456         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1457                 _queue_delete_node(surface_queue, node);
1458
1459         /* Reset queue */
1460         _queue_init(&surface_queue->free_queue);
1461         _queue_init(&surface_queue->dirty_queue);
1462         LIST_INITHEAD(&surface_queue->list);
1463
1464         surface_queue->num_attached = 0;
1465
1466         if (surface_queue->impl && surface_queue->impl->reset)
1467                 surface_queue->impl->reset(surface_queue);
1468
1469         pthread_mutex_unlock(&surface_queue->lock);
1470         pthread_cond_signal(&surface_queue->free_cond);
1471
1472         _tbm_surf_queue_mutex_unlock();
1473
1474         _notify_emit(surface_queue, &surface_queue->reset_noti);
1475
1476         return TBM_SURFACE_QUEUE_ERROR_NONE;
1477 }
1478
1479 tbm_surface_queue_error_e
1480 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1481 {
1482         _tbm_surf_queue_mutex_lock();
1483
1484         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1485                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1486
1487         _tbm_surf_queue_mutex_unlock();
1488
1489         _notify_emit(surface_queue, &surface_queue->reset_noti);
1490
1491         return TBM_SURFACE_QUEUE_ERROR_NONE;
1492 }
1493
1494 tbm_surface_queue_error_e
1495 tbm_surface_queue_set_size(tbm_surface_queue_h
1496                         surface_queue, int queue_size, int flush)
1497 {
1498         queue_node *node = NULL, *tmp;
1499
1500         _tbm_surf_queue_mutex_lock();
1501
1502         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1503                                         TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1504         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1505                                         TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1506
1507         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1508
1509         if ((surface_queue->queue_size == queue_size) && !flush) {
1510                 _tbm_surf_queue_mutex_unlock();
1511                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1512         }
1513
1514         pthread_mutex_lock(&surface_queue->lock);
1515
1516         if (flush) {
1517                 /* Destory surface and Push to free_queue */
1518                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1519                         _queue_delete_node(surface_queue, node);
1520
1521                 /* Reset queue */
1522                 _queue_init(&surface_queue->free_queue);
1523                 _queue_init(&surface_queue->dirty_queue);
1524                 LIST_INITHEAD(&surface_queue->list);
1525
1526                 surface_queue->num_attached = 0;
1527                 surface_queue->queue_size = queue_size;
1528
1529                 if (surface_queue->impl && surface_queue->impl->reset)
1530                         surface_queue->impl->reset(surface_queue);
1531
1532                 pthread_mutex_unlock(&surface_queue->lock);
1533                 pthread_cond_signal(&surface_queue->free_cond);
1534
1535                 _tbm_surf_queue_mutex_unlock();
1536
1537                 _notify_emit(surface_queue, &surface_queue->reset_noti);
1538
1539                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1540         } else {
1541                 if (surface_queue->queue_size > queue_size) {
1542                         int need_del = surface_queue->queue_size - queue_size;
1543
1544                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1545                                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1546
1547                                 if (surface_queue->impl && surface_queue->impl->need_detach)
1548                                         surface_queue->impl->need_detach(surface_queue, node);
1549                                 else
1550                                         _tbm_surface_queue_detach(surface_queue, node->surface);
1551
1552                                 need_del--;
1553                                 if (need_del == 0)
1554                                         break;
1555                         }
1556                 }
1557
1558                 surface_queue->queue_size = queue_size;
1559
1560                 pthread_mutex_unlock(&surface_queue->lock);
1561
1562                 _tbm_surf_queue_mutex_unlock();
1563
1564                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1565         }
1566 }
1567
1568 tbm_surface_queue_error_e
1569 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1570 {
1571         queue_node *node = NULL;
1572
1573         _tbm_surf_queue_mutex_lock();
1574
1575         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1576                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1577
1578         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1579
1580         if (surface_queue->num_attached == 0) {
1581                 _tbm_surf_queue_mutex_unlock();
1582                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1583         }
1584
1585         pthread_mutex_lock(&surface_queue->lock);
1586
1587         /* Destory surface in free_queue */
1588         while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1589                 if (surface_queue->impl && surface_queue->impl->need_detach)
1590                         surface_queue->impl->need_detach(surface_queue, node);
1591                 else
1592                         _tbm_surface_queue_detach(surface_queue, node->surface);
1593         }
1594
1595         /* Reset queue */
1596         _queue_init(&surface_queue->free_queue);
1597
1598         pthread_mutex_unlock(&surface_queue->lock);
1599         _tbm_surf_queue_mutex_unlock();
1600
1601         return TBM_SURFACE_QUEUE_ERROR_NONE;
1602 }
1603
1604 tbm_surface_queue_error_e
1605 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1606 {
1607         queue_node *node = NULL, *tmp;
1608
1609         _tbm_surf_queue_mutex_lock();
1610
1611         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1612                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1613
1614         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1615
1616         if (surface_queue->num_attached == 0) {
1617                 _tbm_surf_queue_mutex_unlock();
1618                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1619         }
1620
1621         pthread_mutex_lock(&surface_queue->lock);
1622
1623         /* Destory surface and Push to free_queue */
1624         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1625                 _queue_delete_node(surface_queue, node);
1626
1627         /* Reset queue */
1628         _queue_init(&surface_queue->free_queue);
1629         _queue_init(&surface_queue->dirty_queue);
1630         LIST_INITHEAD(&surface_queue->list);
1631
1632         surface_queue->num_attached = 0;
1633
1634         if (surface_queue->impl && surface_queue->impl->reset)
1635                 surface_queue->impl->reset(surface_queue);
1636
1637         pthread_mutex_unlock(&surface_queue->lock);
1638         pthread_cond_signal(&surface_queue->free_cond);
1639
1640         _tbm_surf_queue_mutex_unlock();
1641
1642         _notify_emit(surface_queue, &surface_queue->reset_noti);
1643
1644         return TBM_SURFACE_QUEUE_ERROR_NONE;
1645 }
1646
1647 tbm_surface_queue_error_e
1648 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1649                         tbm_surface_h *surfaces, int *num)
1650 {
1651         queue_node *node = NULL;
1652
1653         _tbm_surf_queue_mutex_lock();
1654
1655         *num = 0;
1656
1657         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1658                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1659         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1660                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1661
1662         pthread_mutex_lock(&surface_queue->lock);
1663
1664         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1665                 if (surfaces)
1666                         surfaces[*num] = node->surface;
1667
1668                 *num = *num + 1;
1669         }
1670
1671         pthread_mutex_unlock(&surface_queue->lock);
1672
1673         _tbm_surf_queue_mutex_unlock();
1674
1675         return TBM_SURFACE_QUEUE_ERROR_NONE;
1676 }
1677
1678 tbm_surface_queue_error_e
1679 tbm_surface_queue_get_trace_surface_num(
1680                         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1681 {
1682         _tbm_surf_queue_mutex_lock();
1683
1684         *num = 0;
1685
1686         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1687                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1688         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1689                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1690
1691         pthread_mutex_lock(&surface_queue->lock);
1692
1693         switch (trace) {
1694         case TBM_SURFACE_QUEUE_TRACE_NONE:
1695                 *num = 0;
1696                 break;
1697         case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1698                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1699                 break;
1700         case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1701                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1702                 break;
1703         case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1704                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1705                 break;
1706         case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1707                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1708                 break;
1709         }
1710
1711         pthread_mutex_unlock(&surface_queue->lock);
1712
1713         _tbm_surf_queue_mutex_unlock();
1714
1715         return TBM_SURFACE_QUEUE_ERROR_NONE;
1716 }
1717
1718 typedef struct {
1719         int flags;
1720 } tbm_queue_default;
1721
1722 static void
1723 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1724 {
1725         free(surface_queue->impl_data);
1726 }
1727
1728 static void
1729 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1730 {
1731         tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1732         tbm_surface_h surface;
1733
1734         if (surface_queue->queue_size == surface_queue->num_attached)
1735                 return;
1736
1737         if (surface_queue->alloc_cb) {
1738                 pthread_mutex_unlock(&surface_queue->lock);
1739                 _tbm_surf_queue_mutex_unlock();
1740                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1741                 _tbm_surf_queue_mutex_lock();
1742                 pthread_mutex_lock(&surface_queue->lock);
1743
1744                 /* silent return */
1745                 if (!surface)
1746                         return;
1747
1748                 tbm_surface_internal_ref(surface);
1749         } else {
1750                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1751                                 surface_queue->height,
1752                                 surface_queue->format,
1753                                 data->flags);
1754                 TBM_RETURN_IF_FAIL(surface != NULL);
1755         }
1756
1757         _tbm_surface_queue_attach(surface_queue, surface);
1758         tbm_surface_internal_unref(surface);
1759 }
1760
1761 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1762         NULL,                           /*__tbm_queue_default_init*/
1763         NULL,                           /*__tbm_queue_default_reset*/
1764         __tbm_queue_default_destroy,
1765         __tbm_queue_default_need_attach,
1766         NULL,                           /*__tbm_queue_default_enqueue*/
1767         NULL,                           /*__tbm_queue_default_release*/
1768         NULL,                           /*__tbm_queue_default_dequeue*/
1769         NULL,                           /*__tbm_queue_default_acquire*/
1770         NULL,                           /*__tbm_queue_default_need_detach*/
1771 };
1772
1773 tbm_surface_queue_h
1774 tbm_surface_queue_create(int queue_size, int width,
1775                          int height, int format, int flags)
1776 {
1777         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1778         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1779         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1780         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1781
1782         _tbm_surf_queue_mutex_lock();
1783
1784         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1785                                             sizeof(struct _tbm_surface_queue));
1786         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1787
1788         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1789
1790         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1791                                   sizeof(tbm_queue_default));
1792         if (data == NULL) {
1793                 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1794                 free(surface_queue);
1795                 _tbm_surf_queue_mutex_unlock();
1796                 return NULL;
1797         }
1798
1799         data->flags = flags;
1800         _tbm_surface_queue_init(surface_queue,
1801                                 queue_size,
1802                                 width, height, format,
1803                                 &tbm_queue_default_impl, data);
1804
1805         _tbm_surf_queue_mutex_unlock();
1806
1807         return surface_queue;
1808 }
1809
1810 typedef struct {
1811         int flags;
1812         queue dequeue_list;
1813 } tbm_queue_sequence;
1814
1815 static void
1816 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1817 {
1818         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1819
1820         _queue_init(&data->dequeue_list);
1821 }
1822
1823 static void
1824 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1825 {
1826         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1827
1828         _queue_init(&data->dequeue_list);
1829 }
1830
1831 static void
1832 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1833 {
1834         free(surface_queue->impl_data);
1835 }
1836
1837 static void
1838 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1839 {
1840         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1841         tbm_surface_h surface;
1842
1843         if (surface_queue->queue_size == surface_queue->num_attached)
1844                 return;
1845
1846         if (surface_queue->alloc_cb) {
1847                 pthread_mutex_unlock(&surface_queue->lock);
1848                 _tbm_surf_queue_mutex_unlock();
1849                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1850                 _tbm_surf_queue_mutex_lock();
1851                 pthread_mutex_lock(&surface_queue->lock);
1852
1853                 /* silent return */
1854                 if (!surface)
1855                         return;
1856
1857                 tbm_surface_internal_ref(surface);
1858         } else {
1859                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1860                                 surface_queue->height,
1861                                 surface_queue->format,
1862                                 data->flags);
1863                 TBM_RETURN_IF_FAIL(surface != NULL);
1864         }
1865
1866         _tbm_surface_queue_attach(surface_queue, surface);
1867         tbm_surface_internal_unref(surface);
1868 }
1869
1870 static void
1871 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1872                              queue_node *node)
1873 {
1874         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1875         queue_node *next = NULL, *tmp;
1876
1877         node->priv_flags = 0;
1878
1879         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1880                 if (next->priv_flags)
1881                         break;
1882                 _queue_node_pop(&data->dequeue_list, next);
1883                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1884         }
1885 }
1886
1887 static queue_node *
1888 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1889                              surface_queue)
1890 {
1891         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1892         queue_node *node;
1893
1894         node = _tbm_surface_queue_dequeue(surface_queue);
1895         if (node) {
1896                 _queue_node_push_back(&data->dequeue_list, node);
1897                 node->priv_flags = 1;
1898         }
1899
1900         return node;
1901 }
1902
1903 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1904         __tbm_queue_sequence_init,
1905         __tbm_queue_sequence_reset,
1906         __tbm_queue_sequence_destroy,
1907         __tbm_queue_sequence_need_attach,
1908         __tbm_queue_sequence_enqueue,
1909         NULL,                                   /*__tbm_queue_sequence_release*/
1910         __tbm_queue_sequence_dequeue,
1911         NULL,                                   /*__tbm_queue_sequence_acquire*/
1912         NULL,                                   /*__tbm_queue_sequence_need_dettach*/
1913 };
1914
1915 tbm_surface_queue_h
1916 tbm_surface_queue_sequence_create(int queue_size, int width,
1917                                   int height, int format, int flags)
1918 {
1919         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1920         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1921         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1922         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1923
1924         _tbm_surf_queue_mutex_lock();
1925
1926         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1927                                             sizeof(struct _tbm_surface_queue));
1928         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1929
1930         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1931
1932         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1933                                    sizeof(tbm_queue_sequence));
1934         if (data == NULL) {
1935                 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
1936                 free(surface_queue);
1937                 _tbm_surf_queue_mutex_unlock();
1938                 return NULL;
1939         }
1940
1941         data->flags = flags;
1942         _tbm_surface_queue_init(surface_queue,
1943                                 queue_size,
1944                                 width, height, format,
1945                                 &tbm_queue_sequence_impl, data);
1946
1947         _tbm_surf_queue_mutex_unlock();
1948
1949         return surface_queue;
1950 }
1951 /* LCOV_EXCL_STOP */