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