tbm_surface_queue: add tbm_surface_queue_free_flush
[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                         _tbm_surf_queue_mutex_unlock();
1200                         return 0;
1201                 }
1202         }
1203
1204         if (!_queue_is_empty(&surface_queue->free_queue)) {
1205                 pthread_mutex_unlock(&surface_queue->lock);
1206                 _tbm_surf_queue_mutex_unlock();
1207                 return 1;
1208         }
1209
1210         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1211                                                 QUEUE_NODE_TYPE_ACQUIRE)) {
1212                 _tbm_surf_queue_mutex_unlock();
1213                 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1214                 _tbm_surf_queue_mutex_lock();
1215
1216                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1217                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1218                         pthread_mutex_unlock(&surface_queue->lock);
1219                         _tbm_surf_queue_mutex_unlock();
1220                         return 0;
1221                 }
1222
1223                 pthread_mutex_unlock(&surface_queue->lock);
1224                 _tbm_surf_queue_mutex_unlock();
1225                 return 1;
1226         }
1227
1228         pthread_mutex_unlock(&surface_queue->lock);
1229         _tbm_surf_queue_mutex_unlock();
1230         return 0;
1231 }
1232
1233 tbm_surface_queue_error_e
1234 tbm_surface_queue_release(tbm_surface_queue_h
1235                           surface_queue, tbm_surface_h surface)
1236 {
1237         queue_node *node;
1238         int queue_type;
1239
1240         _tbm_surf_queue_mutex_lock();
1241
1242         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1243                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1244         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1245                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1246
1247         pthread_mutex_lock(&surface_queue->lock);
1248
1249         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1250
1251         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1252         if (node == NULL || queue_type != NODE_LIST) {
1253                 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1254                         node, queue_type);
1255                 pthread_mutex_unlock(&surface_queue->lock);
1256
1257                 _tbm_surf_queue_mutex_unlock();
1258                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1259         }
1260
1261         if (surface_queue->queue_size < surface_queue->num_attached) {
1262                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1263
1264                 if (surface_queue->impl && surface_queue->impl->need_detach)
1265                         surface_queue->impl->need_detach(surface_queue, node);
1266                 else
1267                         _tbm_surface_queue_detach(surface_queue, surface);
1268
1269                 pthread_mutex_unlock(&surface_queue->lock);
1270
1271                 _tbm_surf_queue_mutex_unlock();
1272                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1273         }
1274
1275         if (surface_queue->impl && surface_queue->impl->release)
1276                 surface_queue->impl->release(surface_queue, node);
1277         else
1278                 _tbm_surface_queue_release(surface_queue, node, 1);
1279
1280         if (_queue_is_empty(&surface_queue->free_queue)) {
1281                 pthread_mutex_unlock(&surface_queue->lock);
1282
1283                 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1284                 _tbm_surf_queue_mutex_unlock();
1285                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1286         }
1287
1288         node->type = QUEUE_NODE_TYPE_RELEASE;
1289
1290         pthread_mutex_unlock(&surface_queue->lock);
1291         pthread_cond_signal(&surface_queue->free_cond);
1292
1293         _tbm_surf_queue_mutex_unlock();
1294
1295         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1296
1297         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1298
1299         return TBM_SURFACE_QUEUE_ERROR_NONE;
1300 }
1301
1302 tbm_surface_queue_error_e
1303 tbm_surface_queue_acquire(tbm_surface_queue_h
1304                           surface_queue, tbm_surface_h *surface)
1305 {
1306         queue_node *node;
1307
1308         _tbm_surf_queue_mutex_lock();
1309
1310         *surface = NULL;
1311
1312         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1313                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1314         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1315                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1316
1317         pthread_mutex_lock(&surface_queue->lock);
1318
1319         if (surface_queue->impl && surface_queue->impl->acquire)
1320                 node = surface_queue->impl->acquire(surface_queue);
1321         else
1322                 node = _tbm_surface_queue_acquire(surface_queue);
1323
1324         if (node == NULL || node->surface == NULL) {
1325                 TBM_LOG_E("_queue_node_pop_front failed\n");
1326                 pthread_mutex_unlock(&surface_queue->lock);
1327
1328                 _tbm_surf_queue_mutex_unlock();
1329                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1330         }
1331
1332         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1333
1334         *surface = node->surface;
1335
1336         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1337
1338         pthread_mutex_unlock(&surface_queue->lock);
1339
1340         _tbm_surf_queue_mutex_unlock();
1341
1342         if (b_dump_queue)
1343                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1344
1345         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1346
1347         return TBM_SURFACE_QUEUE_ERROR_NONE;
1348 }
1349
1350 int
1351 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1352 {
1353         _tbm_surf_queue_mutex_lock();
1354
1355         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1356
1357         pthread_mutex_lock(&surface_queue->lock);
1358
1359         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1360
1361         if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1362                 pthread_mutex_unlock(&surface_queue->lock);
1363                 _tbm_surf_queue_mutex_unlock();
1364                 return 1;
1365         }
1366
1367         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1368                                                 QUEUE_NODE_TYPE_DEQUEUE)) {
1369                 _tbm_surf_queue_mutex_unlock();
1370                 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1371                 _tbm_surf_queue_mutex_lock();
1372
1373                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1374                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1375                         pthread_mutex_unlock(&surface_queue->lock);
1376                         _tbm_surf_queue_mutex_unlock();
1377                         return 0;
1378                 }
1379
1380                 pthread_mutex_unlock(&surface_queue->lock);
1381                 _tbm_surf_queue_mutex_unlock();
1382                 return 1;
1383         }
1384
1385         pthread_mutex_unlock(&surface_queue->lock);
1386         _tbm_surf_queue_mutex_unlock();
1387         return 0;
1388 }
1389
1390 void
1391 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1392 {
1393         queue_node *node = NULL, *tmp;
1394
1395         _tbm_surf_queue_mutex_lock();
1396
1397         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1398
1399         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1400
1401         LIST_DEL(&surface_queue->item_link);
1402
1403         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1404                 _queue_delete_node(surface_queue, node);
1405
1406         if (surface_queue->impl && surface_queue->impl->destroy)
1407                 surface_queue->impl->destroy(surface_queue);
1408
1409         _notify_emit(surface_queue, &surface_queue->destory_noti);
1410
1411         _notify_remove_all(&surface_queue->destory_noti);
1412         _notify_remove_all(&surface_queue->dequeuable_noti);
1413         _notify_remove_all(&surface_queue->dequeue_noti);
1414         _notify_remove_all(&surface_queue->can_dequeue_noti);
1415         _notify_remove_all(&surface_queue->acquirable_noti);
1416         _notify_remove_all(&surface_queue->reset_noti);
1417         _trace_remove_all(&surface_queue->trace_noti);
1418
1419         pthread_mutex_destroy(&surface_queue->lock);
1420
1421         free(surface_queue);
1422
1423         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1424                 _deinit_tbm_surf_queue_bufmgr();
1425
1426         _tbm_surf_queue_mutex_unlock();
1427 }
1428
1429 tbm_surface_queue_error_e
1430 tbm_surface_queue_reset(tbm_surface_queue_h
1431                         surface_queue, int width, int height, int format)
1432 {
1433         queue_node *node = NULL, *tmp;
1434
1435         _tbm_surf_queue_mutex_lock();
1436
1437         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1438                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1439
1440         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1441
1442         if (width == surface_queue->width && height == surface_queue->height &&
1443                 format == surface_queue->format) {
1444                 _tbm_surf_queue_mutex_unlock();
1445                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1446         }
1447
1448         pthread_mutex_lock(&surface_queue->lock);
1449
1450         surface_queue->width = width;
1451         surface_queue->height = height;
1452         surface_queue->format = format;
1453
1454         /* Destory surface and Push to free_queue */
1455         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1456                 _queue_delete_node(surface_queue, node);
1457
1458         /* Reset queue */
1459         _queue_init(&surface_queue->free_queue);
1460         _queue_init(&surface_queue->dirty_queue);
1461         LIST_INITHEAD(&surface_queue->list);
1462
1463         surface_queue->num_attached = 0;
1464
1465         if (surface_queue->impl && surface_queue->impl->reset)
1466                 surface_queue->impl->reset(surface_queue);
1467
1468         pthread_mutex_unlock(&surface_queue->lock);
1469         pthread_cond_signal(&surface_queue->free_cond);
1470
1471         _tbm_surf_queue_mutex_unlock();
1472
1473         _notify_emit(surface_queue, &surface_queue->reset_noti);
1474
1475         return TBM_SURFACE_QUEUE_ERROR_NONE;
1476 }
1477
1478 tbm_surface_queue_error_e
1479 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1480 {
1481         _tbm_surf_queue_mutex_lock();
1482
1483         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1484                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1485
1486         _tbm_surf_queue_mutex_unlock();
1487
1488         _notify_emit(surface_queue, &surface_queue->reset_noti);
1489
1490         return TBM_SURFACE_QUEUE_ERROR_NONE;
1491 }
1492
1493 tbm_surface_queue_error_e
1494 tbm_surface_queue_set_size(tbm_surface_queue_h
1495                         surface_queue, int queue_size, int flush)
1496 {
1497         queue_node *node = NULL, *tmp;
1498
1499         _tbm_surf_queue_mutex_lock();
1500
1501         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1502                                         TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1503         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1504                                         TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1505
1506         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1507
1508         if ((surface_queue->queue_size == queue_size) && !flush) {
1509                 _tbm_surf_queue_mutex_unlock();
1510                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1511         }
1512
1513         pthread_mutex_lock(&surface_queue->lock);
1514
1515         if (flush) {
1516                 /* Destory surface and Push to free_queue */
1517                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1518                         _queue_delete_node(surface_queue, node);
1519
1520                 /* Reset queue */
1521                 _queue_init(&surface_queue->free_queue);
1522                 _queue_init(&surface_queue->dirty_queue);
1523                 LIST_INITHEAD(&surface_queue->list);
1524
1525                 surface_queue->num_attached = 0;
1526                 surface_queue->queue_size = queue_size;
1527
1528                 if (surface_queue->impl && surface_queue->impl->reset)
1529                         surface_queue->impl->reset(surface_queue);
1530
1531                 pthread_mutex_unlock(&surface_queue->lock);
1532                 pthread_cond_signal(&surface_queue->free_cond);
1533
1534                 _tbm_surf_queue_mutex_unlock();
1535
1536                 _notify_emit(surface_queue, &surface_queue->reset_noti);
1537
1538                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1539         } else {
1540                 if (surface_queue->queue_size > queue_size) {
1541                         int need_del = surface_queue->queue_size - queue_size;
1542
1543                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1544                                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1545
1546                                 if (surface_queue->impl && surface_queue->impl->need_detach)
1547                                         surface_queue->impl->need_detach(surface_queue, node);
1548                                 else
1549                                         _tbm_surface_queue_detach(surface_queue, node->surface);
1550
1551                                 need_del--;
1552                                 if (need_del == 0)
1553                                         break;
1554                         }
1555                 }
1556
1557                 surface_queue->queue_size = queue_size;
1558
1559                 pthread_mutex_unlock(&surface_queue->lock);
1560
1561                 _tbm_surf_queue_mutex_unlock();
1562
1563                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1564         }
1565 }
1566
1567 tbm_surface_queue_error_e
1568 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1569 {
1570         queue_node *node = NULL;
1571
1572         _tbm_surf_queue_mutex_lock();
1573
1574         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1575                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1576
1577         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1578
1579         if (surface_queue->num_attached == 0) {
1580                 _tbm_surf_queue_mutex_unlock();
1581                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1582         }
1583
1584         pthread_mutex_lock(&surface_queue->lock);
1585
1586         /* Destory surface in free_queue */
1587         while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1588                 if (surface_queue->impl && surface_queue->impl->need_detach)
1589                         surface_queue->impl->need_detach(surface_queue, node);
1590                 else
1591                         _tbm_surface_queue_detach(surface_queue, node->surface);
1592         }
1593
1594         /* Reset queue */
1595         _queue_init(&surface_queue->free_queue);
1596
1597         pthread_mutex_unlock(&surface_queue->lock);
1598         _tbm_surf_queue_mutex_unlock();
1599
1600         return TBM_SURFACE_QUEUE_ERROR_NONE;
1601 }
1602
1603 tbm_surface_queue_error_e
1604 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1605 {
1606         queue_node *node = NULL, *tmp;
1607
1608         _tbm_surf_queue_mutex_lock();
1609
1610         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1611                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1612
1613         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1614
1615         if (surface_queue->num_attached == 0) {
1616                 _tbm_surf_queue_mutex_unlock();
1617                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1618         }
1619
1620         pthread_mutex_lock(&surface_queue->lock);
1621
1622         /* Destory surface and Push to free_queue */
1623         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1624                 _queue_delete_node(surface_queue, node);
1625
1626         /* Reset queue */
1627         _queue_init(&surface_queue->free_queue);
1628         _queue_init(&surface_queue->dirty_queue);
1629         LIST_INITHEAD(&surface_queue->list);
1630
1631         surface_queue->num_attached = 0;
1632
1633         if (surface_queue->impl && surface_queue->impl->reset)
1634                 surface_queue->impl->reset(surface_queue);
1635
1636         pthread_mutex_unlock(&surface_queue->lock);
1637         pthread_cond_signal(&surface_queue->free_cond);
1638
1639         _tbm_surf_queue_mutex_unlock();
1640
1641         _notify_emit(surface_queue, &surface_queue->reset_noti);
1642
1643         return TBM_SURFACE_QUEUE_ERROR_NONE;
1644 }
1645
1646 tbm_surface_queue_error_e
1647 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1648                         tbm_surface_h *surfaces, int *num)
1649 {
1650         queue_node *node = NULL;
1651
1652         _tbm_surf_queue_mutex_lock();
1653
1654         *num = 0;
1655
1656         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1657                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1658         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1659                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1660
1661         pthread_mutex_lock(&surface_queue->lock);
1662
1663         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1664                 if (surfaces)
1665                         surfaces[*num] = node->surface;
1666
1667                 *num = *num + 1;
1668         }
1669
1670         pthread_mutex_unlock(&surface_queue->lock);
1671
1672         _tbm_surf_queue_mutex_unlock();
1673
1674         return TBM_SURFACE_QUEUE_ERROR_NONE;
1675 }
1676
1677 tbm_surface_queue_error_e
1678 tbm_surface_queue_get_trace_surface_num(
1679                         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1680 {
1681         _tbm_surf_queue_mutex_lock();
1682
1683         *num = 0;
1684
1685         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1686                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1687         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1688                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1689
1690         pthread_mutex_lock(&surface_queue->lock);
1691
1692         switch (trace) {
1693         case TBM_SURFACE_QUEUE_TRACE_NONE:
1694                 *num = 0;
1695                 break;
1696         case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1697                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1698                 break;
1699         case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1700                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1701                 break;
1702         case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1703                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1704                 break;
1705         case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1706                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1707                 break;
1708         }
1709
1710         pthread_mutex_unlock(&surface_queue->lock);
1711
1712         _tbm_surf_queue_mutex_unlock();
1713
1714         return TBM_SURFACE_QUEUE_ERROR_NONE;
1715 }
1716
1717 typedef struct {
1718         int flags;
1719 } tbm_queue_default;
1720
1721 static void
1722 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1723 {
1724         free(surface_queue->impl_data);
1725 }
1726
1727 static void
1728 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1729 {
1730         tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1731         tbm_surface_h surface;
1732
1733         if (surface_queue->queue_size == surface_queue->num_attached)
1734                 return;
1735
1736         if (surface_queue->alloc_cb) {
1737                 pthread_mutex_unlock(&surface_queue->lock);
1738                 _tbm_surf_queue_mutex_unlock();
1739                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1740                 _tbm_surf_queue_mutex_lock();
1741                 pthread_mutex_lock(&surface_queue->lock);
1742
1743                 /* silent return */
1744                 if (!surface)
1745                         return;
1746
1747                 tbm_surface_internal_ref(surface);
1748         } else {
1749                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1750                                 surface_queue->height,
1751                                 surface_queue->format,
1752                                 data->flags);
1753                 TBM_RETURN_IF_FAIL(surface != NULL);
1754         }
1755
1756         _tbm_surface_queue_attach(surface_queue, surface);
1757         tbm_surface_internal_unref(surface);
1758 }
1759
1760 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1761         NULL,                           /*__tbm_queue_default_init*/
1762         NULL,                           /*__tbm_queue_default_reset*/
1763         __tbm_queue_default_destroy,
1764         __tbm_queue_default_need_attach,
1765         NULL,                           /*__tbm_queue_default_enqueue*/
1766         NULL,                           /*__tbm_queue_default_release*/
1767         NULL,                           /*__tbm_queue_default_dequeue*/
1768         NULL,                           /*__tbm_queue_default_acquire*/
1769         NULL,                           /*__tbm_queue_default_need_detach*/
1770 };
1771
1772 tbm_surface_queue_h
1773 tbm_surface_queue_create(int queue_size, int width,
1774                          int height, int format, int flags)
1775 {
1776         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1777         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1778         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1779         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1780
1781         _tbm_surf_queue_mutex_lock();
1782
1783         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1784                                             sizeof(struct _tbm_surface_queue));
1785         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1786
1787         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1788
1789         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1790                                   sizeof(tbm_queue_default));
1791         if (data == NULL) {
1792                 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1793                 free(surface_queue);
1794                 _tbm_surf_queue_mutex_unlock();
1795                 return NULL;
1796         }
1797
1798         data->flags = flags;
1799         _tbm_surface_queue_init(surface_queue,
1800                                 queue_size,
1801                                 width, height, format,
1802                                 &tbm_queue_default_impl, data);
1803
1804         _tbm_surf_queue_mutex_unlock();
1805
1806         return surface_queue;
1807 }
1808
1809 typedef struct {
1810         int flags;
1811         queue dequeue_list;
1812 } tbm_queue_sequence;
1813
1814 static void
1815 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1816 {
1817         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1818
1819         _queue_init(&data->dequeue_list);
1820 }
1821
1822 static void
1823 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1824 {
1825         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1826
1827         _queue_init(&data->dequeue_list);
1828 }
1829
1830 static void
1831 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1832 {
1833         free(surface_queue->impl_data);
1834 }
1835
1836 static void
1837 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1838 {
1839         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1840         tbm_surface_h surface;
1841
1842         if (surface_queue->queue_size == surface_queue->num_attached)
1843                 return;
1844
1845         if (surface_queue->alloc_cb) {
1846                 pthread_mutex_unlock(&surface_queue->lock);
1847                 _tbm_surf_queue_mutex_unlock();
1848                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1849                 _tbm_surf_queue_mutex_lock();
1850                 pthread_mutex_lock(&surface_queue->lock);
1851
1852                 /* silent return */
1853                 if (!surface)
1854                         return;
1855
1856                 tbm_surface_internal_ref(surface);
1857         } else {
1858                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1859                                 surface_queue->height,
1860                                 surface_queue->format,
1861                                 data->flags);
1862                 TBM_RETURN_IF_FAIL(surface != NULL);
1863         }
1864
1865         _tbm_surface_queue_attach(surface_queue, surface);
1866         tbm_surface_internal_unref(surface);
1867 }
1868
1869 static void
1870 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1871                              queue_node *node)
1872 {
1873         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1874         queue_node *next = NULL, *tmp;
1875
1876         node->priv_flags = 0;
1877
1878         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1879                 if (next->priv_flags)
1880                         break;
1881                 _queue_node_pop(&data->dequeue_list, next);
1882                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1883         }
1884 }
1885
1886 static queue_node *
1887 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1888                              surface_queue)
1889 {
1890         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1891         queue_node *node;
1892
1893         node = _tbm_surface_queue_dequeue(surface_queue);
1894         if (node) {
1895                 _queue_node_push_back(&data->dequeue_list, node);
1896                 node->priv_flags = 1;
1897         }
1898
1899         return node;
1900 }
1901
1902 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1903         __tbm_queue_sequence_init,
1904         __tbm_queue_sequence_reset,
1905         __tbm_queue_sequence_destroy,
1906         __tbm_queue_sequence_need_attach,
1907         __tbm_queue_sequence_enqueue,
1908         NULL,                                   /*__tbm_queue_sequence_release*/
1909         __tbm_queue_sequence_dequeue,
1910         NULL,                                   /*__tbm_queue_sequence_acquire*/
1911         NULL,                                   /*__tbm_queue_sequence_need_dettach*/
1912 };
1913
1914 tbm_surface_queue_h
1915 tbm_surface_queue_sequence_create(int queue_size, int width,
1916                                   int height, int format, int flags)
1917 {
1918         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1919         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1920         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1921         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1922
1923         _tbm_surf_queue_mutex_lock();
1924
1925         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1926                                             sizeof(struct _tbm_surface_queue));
1927         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1928
1929         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1930
1931         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1932                                    sizeof(tbm_queue_sequence));
1933         if (data == NULL) {
1934                 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
1935                 free(surface_queue);
1936                 _tbm_surf_queue_mutex_unlock();
1937                 return NULL;
1938         }
1939
1940         data->flags = flags;
1941         _tbm_surface_queue_init(surface_queue,
1942                                 queue_size,
1943                                 width, height, format,
1944                                 &tbm_queue_sequence_impl, data);
1945
1946         _tbm_surf_queue_mutex_unlock();
1947
1948         return surface_queue;
1949 }
1950 /* LCOV_EXCL_STOP */