Package version up to 4.1.31
[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 #include <time.h>
37
38 #define FREE_QUEUE      1
39 #define DIRTY_QUEUE     2
40 #define NODE_LIST       4
41
42 #define TBM_SURFACE_QUEUE_MAGIC 0xBF031234
43
44 static pthread_mutex_t tbm_surf_queue_lock = PTHREAD_MUTEX_INITIALIZER;
45 void _tbm_surface_queue_mutex_unlock(void);
46
47 /* check condition */
48 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
49         if (!(cond)) {\
50                 TBM_ERR("'%s' failed.", #cond);\
51                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
52                 _tbm_surf_queue_mutex_unlock();\
53                 return;\
54         } \
55 }
56
57 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
58         if (!(cond)) {\
59                 TBM_ERR("'%s' failed.", #cond);\
60                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
61                 _tbm_surf_queue_mutex_unlock();\
62                 return val;\
63         } \
64 }
65
66 typedef enum _queue_node_type {
67         QUEUE_NODE_TYPE_NONE,
68         QUEUE_NODE_TYPE_DEQUEUE,
69         QUEUE_NODE_TYPE_ENQUEUE,
70         QUEUE_NODE_TYPE_ACQUIRE,
71         QUEUE_NODE_TYPE_RELEASE
72 } Queue_Node_Type;
73
74 typedef struct {
75         struct list_head head;
76         int count;
77 } queue;
78
79 typedef struct {
80         tbm_surface_h surface;
81
82         struct list_head item_link;
83         struct list_head link;
84
85         Queue_Node_Type type;
86
87         unsigned int priv_flags;        /*for each queue*/
88
89         int delete_pending;
90 } queue_node;
91
92 typedef struct {
93         struct list_head link;
94
95         tbm_surface_queue_notify_cb cb;
96         void *data;
97 } queue_notify;
98
99 typedef struct {
100         struct list_head link;
101
102         tbm_surface_queue_trace_cb cb;
103         void *data;
104 } queue_trace;
105
106 typedef struct _tbm_surface_queue_interface {
107         void (*init)(tbm_surface_queue_h queue);
108         void (*reset)(tbm_surface_queue_h queue);
109         void (*destroy)(tbm_surface_queue_h queue);
110         void (*need_attach)(tbm_surface_queue_h queue);
111
112         void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
113         void (*release)(tbm_surface_queue_h queue, queue_node *node);
114         queue_node *(*dequeue)(tbm_surface_queue_h queue);
115         queue_node *(*acquire)(tbm_surface_queue_h queue);
116         void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
117 } tbm_surface_queue_interface;
118
119 struct _tbm_surface_queue {
120         unsigned int magic;
121         int width;
122         int height;
123         int format;
124         int queue_size;
125         int flags;
126         int num_attached;
127
128         queue free_queue;
129         queue dirty_queue;
130         struct list_head list;
131
132         struct list_head destory_noti;
133         struct list_head dequeuable_noti;
134         struct list_head dequeue_noti;
135         struct list_head can_dequeue_noti;
136         struct list_head acquirable_noti;
137         struct list_head reset_noti;
138         struct list_head trace_noti;
139
140         pthread_mutex_t lock;
141         pthread_cond_t free_cond;
142         pthread_cond_t dirty_cond;
143
144         const tbm_surface_queue_interface *impl;
145         void *impl_data;
146
147         //For external buffer allocation
148         tbm_surface_alloc_cb alloc_cb;
149         tbm_surface_alloc_cb2 alloc_cb2;
150         tbm_surface_free_cb free_cb;
151         void *alloc_cb_data;
152
153         int modes;
154         unsigned int enqueue_sync_count;
155         unsigned int acquire_sync_count;
156 };
157
158 static void
159 _tbm_surf_queue_mutex_lock(void)
160 {
161         pthread_mutex_lock(&tbm_surf_queue_lock);
162 }
163
164 static void
165 _tbm_surf_queue_mutex_unlock(void)
166 {
167         pthread_mutex_unlock(&tbm_surf_queue_lock);
168 }
169
170 static int
171 _tbm_surface_queue_magic_check(tbm_surface_queue_h surface_queue)
172 {
173         if (surface_queue->magic != TBM_SURFACE_QUEUE_MAGIC)
174                 return 0;
175
176         return 1;
177 }
178
179 static int
180 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
181 {
182         if (!surface_queue) {
183                 TBM_ERR("error: surface_queue is NULL.");
184                 return 0;
185         }
186
187         if (!_tbm_surface_queue_magic_check(surface_queue)) {
188                 TBM_ERR("error: Invalid tbm_surface_queue(%p)", surface_queue);
189                 return 0;
190         }
191
192         return 1;
193 }
194
195 static queue_node *
196 _queue_node_create(void)
197 {
198         queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
199
200         TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
201
202         return node;
203 }
204
205 static void
206 _queue_node_delete(queue_node *node)
207 {
208         LIST_DEL(&node->item_link);
209         LIST_DEL(&node->link);
210         free(node);
211 }
212
213 static int
214 _queue_is_empty(queue *queue)
215 {
216         if (LIST_IS_EMPTY(&queue->head))
217                 return 1;
218
219         return 0;
220 }
221
222 static void
223 _queue_node_push_back(queue *queue, queue_node *node)
224 {
225         LIST_ADDTAIL(&node->item_link, &queue->head);
226         queue->count++;
227 }
228
229 static void
230 _queue_node_push_front(queue *queue, queue_node *node)
231 {
232         LIST_ADD(&node->item_link, &queue->head);
233         queue->count++;
234 }
235
236 static queue_node *
237 _queue_node_pop_front(queue *queue)
238 {
239         queue_node *node;
240
241         if (!queue->head.next) return NULL;
242         if (!queue->count) return NULL;
243
244         node = LIST_ENTRY(queue_node, queue->head.next, item_link);
245
246         LIST_DELINIT(&node->item_link);
247         queue->count--;
248
249         return node;
250 }
251
252 static queue_node *
253 _queue_node_pop(queue *queue, queue_node *node)
254 {
255         LIST_DELINIT(&node->item_link);
256         queue->count--;
257
258         return node;
259 }
260
261 static queue_node *
262 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
263                 tbm_surface_h surface, int *out_type)
264 {
265         queue_node *node = NULL;
266
267         if (type == 0)
268                 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
269         if (out_type)
270                 *out_type = 0;
271
272         if (type & FREE_QUEUE) {
273                 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
274                                          item_link) {
275                         if (node->surface == surface) {
276                                 if (out_type)
277                                         *out_type = FREE_QUEUE;
278
279                                 return node;
280                         }
281                 }
282         }
283
284         if (type & DIRTY_QUEUE) {
285                 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
286                                          item_link) {
287                         if (node->surface == surface) {
288                                 if (out_type)
289                                         *out_type = DIRTY_QUEUE;
290
291                                 return node;
292                         }
293                 }
294         }
295
296         if (type & NODE_LIST) {
297                 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
298                         if (node->surface == surface) {
299                                 if (out_type)
300                                         *out_type = NODE_LIST;
301
302                                 return node;
303                         }
304                 }
305         }
306
307         TBM_ERR("fail to get the queue_node.");
308
309         return NULL;
310 }
311
312 static void
313 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
314 {
315         if (node->surface) {
316                 if (surface_queue->free_cb) {
317                         surface_queue->free_cb(surface_queue,
318                                         surface_queue->alloc_cb_data,
319                                         node->surface);
320                 }
321
322                 tbm_surface_destroy(node->surface);
323         }
324
325         _queue_node_delete(node);
326 }
327
328 static void
329 _queue_init(queue *queue)
330 {
331         LIST_INITHEAD(&queue->head);
332
333         queue->count = 0;
334 }
335
336 static void
337 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
338             void *data)
339 {
340         TBM_RETURN_IF_FAIL(cb != NULL);
341
342         queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
343
344         TBM_RETURN_IF_FAIL(item != NULL);
345
346         LIST_INITHEAD(&item->link);
347         item->cb = cb;
348         item->data = data;
349
350         LIST_ADDTAIL(&item->link, list);
351 }
352
353 static void
354 _notify_remove(struct list_head *list,
355                tbm_surface_queue_notify_cb cb, void *data)
356 {
357         queue_notify *item = NULL, *tmp;
358
359         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
360                 if (item->cb == cb && item->data == data) {
361                         LIST_DEL(&item->link);
362                         free(item);
363                         return;
364                 }
365         }
366
367         TBM_ERR("Cannot find notifiy");
368 }
369
370 static void
371 _notify_remove_all(struct list_head *list)
372 {
373         queue_notify *item = NULL, *tmp;
374
375         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
376                 LIST_DEL(&item->link);
377                 free(item);
378         }
379 }
380
381 static void
382 _notify_emit(tbm_surface_queue_h surface_queue,
383              struct list_head *list)
384 {
385         queue_notify *item = NULL, *tmp;;
386
387         /*
388                 The item->cb is the outside function of the libtbm.
389                 The tbm user may/can remove the item of the list,
390                 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
391         */
392         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
393                 item->cb(surface_queue, item->data);
394 }
395
396 static void
397 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
398             void *data)
399 {
400         TBM_RETURN_IF_FAIL(cb != NULL);
401
402         queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
403
404         TBM_RETURN_IF_FAIL(item != NULL);
405
406         LIST_INITHEAD(&item->link);
407         item->cb = cb;
408         item->data = data;
409
410         LIST_ADDTAIL(&item->link, list);
411 }
412
413 static void
414 _trace_remove(struct list_head *list,
415                tbm_surface_queue_trace_cb cb, void *data)
416 {
417         queue_trace *item = NULL, *tmp;
418
419         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
420                 if (item->cb == cb && item->data == data) {
421                         LIST_DEL(&item->link);
422                         free(item);
423                         return;
424                 }
425         }
426
427         TBM_ERR("Cannot find notifiy");
428 }
429
430 static void
431 _trace_remove_all(struct list_head *list)
432 {
433         queue_trace *item = NULL, *tmp;
434
435         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
436                 LIST_DEL(&item->link);
437                 free(item);
438         }
439 }
440
441 static void
442 _trace_emit(tbm_surface_queue_h surface_queue,
443              struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
444 {
445         queue_trace *item = NULL, *tmp;;
446
447         /*
448                 The item->cb is the outside function of the libtbm.
449                 The tbm user may/can remove the item of the list,
450                 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
451         */
452         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
453                 item->cb(surface_queue, surface, trace, item->data);
454 }
455
456 static int
457 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
458 {
459         queue_node *node = NULL;
460         int count = 0;
461
462         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
463                 if (node->type == type)
464                         count++;
465         }
466
467         return count;
468 }
469
470 static void
471 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
472                           tbm_surface_h surface)
473 {
474         queue_node *node;
475
476         node = _queue_node_create();
477         TBM_RETURN_IF_FAIL(node != NULL);
478
479         tbm_surface_internal_ref(surface);
480         node->surface = surface;
481
482         LIST_ADDTAIL(&node->link, &surface_queue->list);
483         surface_queue->num_attached++;
484         _queue_node_push_back(&surface_queue->free_queue, node);
485 }
486
487 static void
488 _tbm_surface_queue_need_attach(tbm_surface_queue_h surface_queue)
489 {
490         tbm_surface_h surface;
491
492         if (surface_queue->queue_size == surface_queue->num_attached)
493                 return;
494
495         if (surface_queue->alloc_cb2) {
496                 surface = surface_queue->alloc_cb2(surface_queue,
497                                 surface_queue->width, surface_queue->height,
498                                 surface_queue->format, surface_queue->flags,
499                                 surface_queue->alloc_cb_data);
500                 if (!surface)
501                         return;
502
503                 tbm_surface_internal_ref(surface);
504         } else if (surface_queue->alloc_cb){
505                 surface = surface_queue->alloc_cb(surface_queue,
506                                 surface_queue->alloc_cb_data);
507                 if (!surface)
508                         return;
509
510                 tbm_surface_internal_ref(surface);
511         } else {
512                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
513                                 surface_queue->height,
514                                 surface_queue->format,
515                                 surface_queue->flags);
516                 TBM_RETURN_IF_FAIL(surface != NULL);
517         }
518
519         _tbm_surface_queue_attach(surface_queue, surface);
520         tbm_surface_internal_unref(surface);
521 }
522
523 static void
524 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
525                           tbm_surface_h surface)
526 {
527         queue_node *node;
528         int queue_type;
529
530         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
531         if (node) {
532                 _queue_delete_node(surface_queue, node);
533                 surface_queue->num_attached--;
534         }
535 }
536
537 static void
538 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
539                            queue_node *node, int push_back)
540 {
541         if (push_back)
542                 _queue_node_push_back(&surface_queue->dirty_queue, node);
543         else
544                 _queue_node_push_front(&surface_queue->dirty_queue, node);
545 }
546
547 static queue_node *
548 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
549 {
550         queue_node *node;
551
552         node = _queue_node_pop_front(&surface_queue->free_queue);
553
554         return node;
555 }
556
557 static queue_node *
558 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
559 {
560         queue_node *node;
561
562         if (_queue_is_empty(&surface_queue->dirty_queue))
563                 return NULL;
564
565         node = _queue_node_pop_front(&surface_queue->dirty_queue);
566
567         return node;
568 }
569
570 static void
571 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
572                            queue_node *node, int push_back)
573 {
574         if (push_back)
575                 _queue_node_push_back(&surface_queue->free_queue, node);
576         else
577                 _queue_node_push_front(&surface_queue->free_queue, node);
578 }
579
580 static void
581 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
582                         int queue_size,
583                         int width, int height, int format, int flags,
584                         const tbm_surface_queue_interface *impl, void *data)
585 {
586         pthread_condattr_t free_attr, dirty_attr;
587
588         TBM_RETURN_IF_FAIL(surface_queue != NULL);
589         TBM_RETURN_IF_FAIL(impl != NULL);
590
591         pthread_mutex_init(&surface_queue->lock, NULL);
592
593         pthread_condattr_init(&free_attr);
594         pthread_condattr_setclock(&free_attr, CLOCK_MONOTONIC);
595         pthread_cond_init(&surface_queue->free_cond, &free_attr);
596         pthread_condattr_destroy(&free_attr);
597
598         pthread_condattr_init(&dirty_attr);
599         pthread_condattr_setclock(&dirty_attr, CLOCK_MONOTONIC);
600         pthread_cond_init(&surface_queue->dirty_cond, &dirty_attr);
601         pthread_condattr_destroy(&dirty_attr);
602
603         surface_queue->magic = TBM_SURFACE_QUEUE_MAGIC;
604         surface_queue->queue_size = queue_size;
605         surface_queue->width = width;
606         surface_queue->height = height;
607         surface_queue->format = format;
608         surface_queue->flags = flags;
609         surface_queue->impl = impl;
610         surface_queue->impl_data = data;
611         surface_queue->modes = TBM_SURFACE_QUEUE_MODE_NONE;
612
613         _queue_init(&surface_queue->free_queue);
614         _queue_init(&surface_queue->dirty_queue);
615         LIST_INITHEAD(&surface_queue->list);
616
617         LIST_INITHEAD(&surface_queue->destory_noti);
618         LIST_INITHEAD(&surface_queue->dequeuable_noti);
619         LIST_INITHEAD(&surface_queue->dequeue_noti);
620         LIST_INITHEAD(&surface_queue->can_dequeue_noti);
621         LIST_INITHEAD(&surface_queue->acquirable_noti);
622         LIST_INITHEAD(&surface_queue->reset_noti);
623         LIST_INITHEAD(&surface_queue->trace_noti);
624
625         if (surface_queue->impl && surface_queue->impl->init)
626                 surface_queue->impl->init(surface_queue);
627 }
628
629 tbm_surface_queue_error_e
630 tbm_surface_queue_add_destroy_cb(
631         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
632         void *data)
633 {
634         _tbm_surf_queue_mutex_lock();
635         _tbm_set_last_result(TBM_ERROR_NONE);
636
637         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
638                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
639         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(destroy_cb,
640                                TBM_ERROR_INVALID_PARAMETER);
641
642         pthread_mutex_lock(&surface_queue->lock);
643
644         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
645
646         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
647
648         pthread_mutex_unlock(&surface_queue->lock);
649
650         _tbm_surf_queue_mutex_unlock();
651
652         return TBM_SURFACE_QUEUE_ERROR_NONE;
653 }
654
655 tbm_surface_queue_error_e
656 tbm_surface_queue_remove_destroy_cb(
657         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
658         void *data)
659 {
660         _tbm_surf_queue_mutex_lock();
661         _tbm_set_last_result(TBM_ERROR_NONE);
662
663         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
664                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
665
666         pthread_mutex_lock(&surface_queue->lock);
667
668         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
669
670         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
671
672         pthread_mutex_unlock(&surface_queue->lock);
673
674         _tbm_surf_queue_mutex_unlock();
675
676         return TBM_SURFACE_QUEUE_ERROR_NONE;
677 }
678
679 tbm_surface_queue_error_e
680 tbm_surface_queue_add_dequeuable_cb(
681         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
682         void *data)
683 {
684         _tbm_surf_queue_mutex_lock();
685         _tbm_set_last_result(TBM_ERROR_NONE);
686
687         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
688                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
689         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(dequeuable_cb,
690                                TBM_ERROR_INVALID_PARAMETER);
691
692         pthread_mutex_lock(&surface_queue->lock);
693
694         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
695
696         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
697
698         pthread_mutex_unlock(&surface_queue->lock);
699
700         _tbm_surf_queue_mutex_unlock();
701
702         return TBM_SURFACE_QUEUE_ERROR_NONE;
703 }
704
705 tbm_surface_queue_error_e
706 tbm_surface_queue_remove_dequeuable_cb(
707         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
708         void *data)
709 {
710         _tbm_surf_queue_mutex_lock();
711         _tbm_set_last_result(TBM_ERROR_NONE);
712
713         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
714                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
715
716         pthread_mutex_lock(&surface_queue->lock);
717
718         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
719
720         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
721
722         pthread_mutex_unlock(&surface_queue->lock);
723
724         _tbm_surf_queue_mutex_unlock();
725
726         return TBM_SURFACE_QUEUE_ERROR_NONE;
727 }
728
729 tbm_surface_queue_error_e
730 tbm_surface_queue_add_dequeue_cb(
731         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
732         void *data)
733 {
734         _tbm_surf_queue_mutex_lock();
735         _tbm_set_last_result(TBM_ERROR_NONE);
736
737         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
738                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
739         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(dequeue_cb,
740                                TBM_ERROR_INVALID_PARAMETER);
741
742         pthread_mutex_lock(&surface_queue->lock);
743
744         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
745
746         _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
747
748         pthread_mutex_unlock(&surface_queue->lock);
749
750         _tbm_surf_queue_mutex_unlock();
751
752         return TBM_SURFACE_QUEUE_ERROR_NONE;
753 }
754
755 tbm_surface_queue_error_e
756 tbm_surface_queue_remove_dequeue_cb(
757         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
758         void *data)
759 {
760         _tbm_surf_queue_mutex_lock();
761         _tbm_set_last_result(TBM_ERROR_NONE);
762
763         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
764                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
765
766         pthread_mutex_lock(&surface_queue->lock);
767
768         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
769
770         _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
771
772         pthread_mutex_unlock(&surface_queue->lock);
773
774         _tbm_surf_queue_mutex_unlock();
775
776         return TBM_SURFACE_QUEUE_ERROR_NONE;
777 }
778
779 tbm_surface_queue_error_e
780 tbm_surface_queue_add_can_dequeue_cb(
781         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
782         void *data)
783 {
784         _tbm_surf_queue_mutex_lock();
785         _tbm_set_last_result(TBM_ERROR_NONE);
786
787         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
788                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
789         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(can_dequeue_cb,
790                                TBM_ERROR_INVALID_PARAMETER);
791
792         pthread_mutex_lock(&surface_queue->lock);
793
794         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
795
796         _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
797
798         pthread_mutex_unlock(&surface_queue->lock);
799
800         _tbm_surf_queue_mutex_unlock();
801
802         return TBM_SURFACE_QUEUE_ERROR_NONE;
803 }
804
805 tbm_surface_queue_error_e
806 tbm_surface_queue_remove_can_dequeue_cb(
807         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
808         void *data)
809 {
810         _tbm_surf_queue_mutex_lock();
811         _tbm_set_last_result(TBM_ERROR_NONE);
812
813         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
814                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
815
816         pthread_mutex_lock(&surface_queue->lock);
817
818         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
819
820         _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
821
822         pthread_mutex_unlock(&surface_queue->lock);
823
824         _tbm_surf_queue_mutex_unlock();
825
826         return TBM_SURFACE_QUEUE_ERROR_NONE;
827 }
828
829 tbm_surface_queue_error_e
830 tbm_surface_queue_add_acquirable_cb(
831         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
832         void *data)
833 {
834         _tbm_surf_queue_mutex_lock();
835         _tbm_set_last_result(TBM_ERROR_NONE);
836
837         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
838                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
839         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(acquirable_cb,
840                                TBM_ERROR_INVALID_PARAMETER);
841
842         pthread_mutex_lock(&surface_queue->lock);
843
844         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
845
846         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
847
848         pthread_mutex_unlock(&surface_queue->lock);
849
850         _tbm_surf_queue_mutex_unlock();
851
852         return TBM_SURFACE_QUEUE_ERROR_NONE;
853 }
854
855 tbm_surface_queue_error_e
856 tbm_surface_queue_remove_acquirable_cb(
857         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
858         void *data)
859 {
860         _tbm_surf_queue_mutex_lock();
861         _tbm_set_last_result(TBM_ERROR_NONE);
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_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", 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         _tbm_set_last_result(TBM_ERROR_NONE);
886
887         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
888                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
889         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(trace_cb,
890                                TBM_ERROR_INVALID_PARAMETER);
891
892         pthread_mutex_lock(&surface_queue->lock);
893
894         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
895
896         _trace_add(&surface_queue->trace_noti, trace_cb, data);
897
898         pthread_mutex_unlock(&surface_queue->lock);
899
900         _tbm_surf_queue_mutex_unlock();
901
902         return TBM_SURFACE_QUEUE_ERROR_NONE;
903 }
904
905 tbm_surface_queue_error_e
906 tbm_surface_queue_remove_trace_cb(
907         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
908         void *data)
909 {
910         _tbm_surf_queue_mutex_lock();
911         _tbm_set_last_result(TBM_ERROR_NONE);
912
913         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
914                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
915
916         pthread_mutex_lock(&surface_queue->lock);
917
918         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
919
920         _trace_remove(&surface_queue->trace_noti, trace_cb, data);
921
922         pthread_mutex_unlock(&surface_queue->lock);
923
924         _tbm_surf_queue_mutex_unlock();
925
926         return TBM_SURFACE_QUEUE_ERROR_NONE;
927 }
928
929 tbm_surface_queue_error_e
930 tbm_surface_queue_set_alloc_cb(
931         tbm_surface_queue_h surface_queue,
932         tbm_surface_alloc_cb alloc_cb,
933         tbm_surface_free_cb free_cb,
934         void *data)
935 {
936         _tbm_surf_queue_mutex_lock();
937         _tbm_set_last_result(TBM_ERROR_NONE);
938
939         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
940                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
941
942         pthread_mutex_lock(&surface_queue->lock);
943
944         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
945
946         if (surface_queue->alloc_cb2) {
947                 TBM_ERR("must use either alloc_cb or alloc_cb2");
948                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
949                 pthread_mutex_unlock(&surface_queue->lock);
950                 _tbm_surf_queue_mutex_unlock();
951                 return TBM_ERROR_INVALID_OPERATION;
952         }
953
954         surface_queue->alloc_cb = alloc_cb;
955         surface_queue->free_cb = free_cb;
956         surface_queue->alloc_cb_data = data;
957
958         pthread_mutex_unlock(&surface_queue->lock);
959
960         _tbm_surf_queue_mutex_unlock();
961
962         return TBM_SURFACE_QUEUE_ERROR_NONE;
963 }
964
965 tbm_surface_queue_error_e
966 tbm_surface_queue_set_alloc_cb2(
967         tbm_surface_queue_h surface_queue,
968         tbm_surface_alloc_cb2 alloc_cb2,
969         tbm_surface_free_cb free_cb,
970         void *data)
971 {
972         _tbm_surf_queue_mutex_lock();
973         _tbm_set_last_result(TBM_ERROR_NONE);
974
975         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
976                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
977
978         pthread_mutex_lock(&surface_queue->lock);
979
980         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
981
982         if (surface_queue->alloc_cb) {
983                 TBM_ERR("must use either alloc_cb or alloc_cb2");
984                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
985                 pthread_mutex_unlock(&surface_queue->lock);
986                 _tbm_surf_queue_mutex_unlock();
987                 return TBM_ERROR_INVALID_OPERATION;
988         }
989
990         surface_queue->alloc_cb2 = alloc_cb2;
991         surface_queue->free_cb = free_cb;
992         surface_queue->alloc_cb_data = data;
993
994         pthread_mutex_unlock(&surface_queue->lock);
995
996         _tbm_surf_queue_mutex_unlock();
997
998         return TBM_SURFACE_QUEUE_ERROR_NONE;
999 }
1000
1001 int
1002 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
1003 {
1004         int width;
1005
1006         _tbm_surf_queue_mutex_lock();
1007         _tbm_set_last_result(TBM_ERROR_NONE);
1008
1009         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1010
1011         pthread_mutex_lock(&surface_queue->lock);
1012
1013         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1014
1015         width = surface_queue->width;
1016
1017         pthread_mutex_unlock(&surface_queue->lock);
1018
1019         _tbm_surf_queue_mutex_unlock();
1020
1021         return width;
1022 }
1023
1024 int
1025 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
1026 {
1027         int height;
1028
1029         _tbm_surf_queue_mutex_lock();
1030         _tbm_set_last_result(TBM_ERROR_NONE);
1031
1032         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1033
1034         pthread_mutex_lock(&surface_queue->lock);
1035
1036         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1037
1038         height = surface_queue->height;
1039
1040         pthread_mutex_unlock(&surface_queue->lock);
1041
1042         _tbm_surf_queue_mutex_unlock();
1043
1044         return height;
1045 }
1046
1047 int
1048 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
1049 {
1050         int format;
1051
1052         _tbm_surf_queue_mutex_lock();
1053         _tbm_set_last_result(TBM_ERROR_NONE);
1054
1055         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1056
1057         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1058
1059         pthread_mutex_lock(&surface_queue->lock);
1060
1061         format = surface_queue->format;
1062
1063         pthread_mutex_unlock(&surface_queue->lock);
1064
1065         _tbm_surf_queue_mutex_unlock();
1066
1067         return format;
1068 }
1069
1070 int
1071 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1072 {
1073         int queue_size;
1074
1075         _tbm_surf_queue_mutex_lock();
1076         _tbm_set_last_result(TBM_ERROR_NONE);
1077
1078         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1079
1080         pthread_mutex_lock(&surface_queue->lock);
1081
1082         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1083
1084         queue_size = surface_queue->queue_size;
1085
1086         pthread_mutex_unlock(&surface_queue->lock);
1087
1088         _tbm_surf_queue_mutex_unlock();
1089
1090         return queue_size;
1091 }
1092
1093 tbm_surface_queue_error_e
1094 tbm_surface_queue_add_reset_cb(
1095         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1096         void *data)
1097 {
1098         _tbm_surf_queue_mutex_lock();
1099         _tbm_set_last_result(TBM_ERROR_NONE);
1100
1101         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1102                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1103         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(reset_cb,
1104                                TBM_ERROR_INVALID_PARAMETER);
1105
1106         pthread_mutex_lock(&surface_queue->lock);
1107
1108         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1109
1110         _notify_add(&surface_queue->reset_noti, reset_cb, data);
1111
1112         pthread_mutex_unlock(&surface_queue->lock);
1113
1114         _tbm_surf_queue_mutex_unlock();
1115
1116         return TBM_SURFACE_QUEUE_ERROR_NONE;
1117 }
1118
1119 tbm_surface_queue_error_e
1120 tbm_surface_queue_remove_reset_cb(
1121         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1122         void *data)
1123 {
1124         _tbm_surf_queue_mutex_lock();
1125         _tbm_set_last_result(TBM_ERROR_NONE);
1126
1127         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1128                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1129
1130         pthread_mutex_lock(&surface_queue->lock);
1131
1132         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1133
1134         _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1135
1136         pthread_mutex_unlock(&surface_queue->lock);
1137
1138         _tbm_surf_queue_mutex_unlock();
1139
1140         return TBM_SURFACE_QUEUE_ERROR_NONE;
1141 }
1142
1143 tbm_surface_queue_error_e
1144 tbm_surface_queue_enqueue(tbm_surface_queue_h
1145                           surface_queue, tbm_surface_h surface)
1146 {
1147         queue_node *node;
1148         int queue_type;
1149
1150         _tbm_surf_queue_mutex_lock();
1151         _tbm_set_last_result(TBM_ERROR_NONE);
1152
1153         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1154                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1155         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1156                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1157
1158         if (b_dump_queue)
1159                 tbm_surface_internal_dump_buffer(surface, "enqueue");
1160
1161         pthread_mutex_lock(&surface_queue->lock);
1162
1163         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, surface);
1164
1165         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1166         if (node == NULL || queue_type != NODE_LIST) {
1167                 TBM_ERR("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d",
1168                         node, queue_type);
1169                 pthread_mutex_unlock(&surface_queue->lock);
1170
1171                 _tbm_surf_queue_mutex_unlock();
1172
1173                 if (!node) {
1174                         _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE);
1175                         return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1176                 } else {
1177                         _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST);
1178                         return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1179                 }
1180         }
1181
1182         if (surface_queue->impl && surface_queue->impl->enqueue)
1183                 surface_queue->impl->enqueue(surface_queue, node);
1184         else
1185                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1186
1187         if (!_queue_get_node(surface_queue, DIRTY_QUEUE, surface, NULL)) {
1188                 TBM_ERR("enqueue surface(%p) but surface isn't present in the dirty_queue", surface);
1189                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_INVALID_SEQUENCE);
1190                 pthread_mutex_unlock(&surface_queue->lock);
1191
1192                 _tbm_surf_queue_mutex_unlock();
1193                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SEQUENCE;
1194         }
1195
1196         node->type = QUEUE_NODE_TYPE_ENQUEUE;
1197
1198         if (surface_queue->enqueue_sync_count == 1) {
1199                 tbm_surface_info_s info;
1200                 int ret;
1201
1202                 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ, &info);
1203                 if (ret == TBM_SURFACE_ERROR_NONE)
1204                         tbm_surface_unmap(surface);
1205         }
1206
1207         if (surface_queue->enqueue_sync_count > 0) surface_queue->enqueue_sync_count--;
1208
1209         pthread_mutex_unlock(&surface_queue->lock);
1210         pthread_cond_signal(&surface_queue->dirty_cond);
1211
1212         _tbm_surf_queue_mutex_unlock();
1213
1214         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1215
1216         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1217
1218         return TBM_SURFACE_QUEUE_ERROR_NONE;
1219 }
1220
1221 tbm_surface_queue_error_e
1222 tbm_surface_queue_cancel_dequeue(tbm_surface_queue_h
1223                           surface_queue, tbm_surface_h surface)
1224 {
1225         queue_node *node;
1226         int queue_type;
1227
1228         _tbm_surf_queue_mutex_lock();
1229         _tbm_set_last_result(TBM_ERROR_NONE);
1230
1231         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1232                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1233         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1234                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1235
1236         pthread_mutex_lock(&surface_queue->lock);
1237
1238         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, surface);
1239
1240         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1241         if (node == NULL || queue_type != NODE_LIST) {
1242                 TBM_ERR("tbm_surface_queue_cancel_dequeue::Surface is existed in free_queue or dirty_queue node:%p, type:%d",
1243                         node, queue_type);
1244                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1245                 pthread_mutex_unlock(&surface_queue->lock);
1246
1247                 _tbm_surf_queue_mutex_unlock();
1248                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1249         }
1250
1251         if (node->delete_pending) {
1252                 TBM_TRACE_SURFACE_QUEUE("delete pending tbm_surface_queue(%p) surface(%p)", surface_queue, node->surface);
1253
1254                 _queue_delete_node(surface_queue, node);
1255
1256                 pthread_mutex_unlock(&surface_queue->lock);
1257
1258                 _tbm_surf_queue_mutex_unlock();
1259
1260                 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1261
1262                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1263         }
1264
1265         if (surface_queue->queue_size < surface_queue->num_attached) {
1266                 TBM_TRACE_SURFACE_QUEUE("deatch tbm_surface_queue(%p) surface(%p)", surface_queue, node->surface);
1267
1268                 if (surface_queue->impl && surface_queue->impl->need_detach)
1269                         surface_queue->impl->need_detach(surface_queue, node);
1270                 else
1271                         _tbm_surface_queue_detach(surface_queue, surface);
1272
1273                 pthread_mutex_unlock(&surface_queue->lock);
1274
1275                 _tbm_surf_queue_mutex_unlock();
1276
1277                 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1278
1279                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1280         }
1281
1282         if (surface_queue->impl && surface_queue->impl->release)
1283                 surface_queue->impl->release(surface_queue, node);
1284         else
1285                 _tbm_surface_queue_release(surface_queue, node, 1);
1286
1287         if (_queue_is_empty(&surface_queue->free_queue)) {
1288                 TBM_ERR("surface_queue->free_queue is empty.");
1289                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1290                 pthread_mutex_unlock(&surface_queue->lock);
1291
1292                 _tbm_surf_queue_mutex_unlock();
1293                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1294         }
1295
1296         node->type = QUEUE_NODE_TYPE_RELEASE;
1297
1298         pthread_mutex_unlock(&surface_queue->lock);
1299         pthread_cond_signal(&surface_queue->free_cond);
1300
1301         _tbm_surf_queue_mutex_unlock();
1302
1303         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1304
1305         return TBM_SURFACE_QUEUE_ERROR_NONE;
1306 }
1307
1308 tbm_surface_queue_error_e
1309 tbm_surface_queue_dequeue(tbm_surface_queue_h
1310                           surface_queue, tbm_surface_h *surface)
1311 {
1312         queue_node *node;
1313
1314         _tbm_surf_queue_mutex_lock();
1315         _tbm_set_last_result(TBM_ERROR_NONE);
1316
1317         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1318                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1319         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1320                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1321
1322         *surface = NULL;
1323
1324         pthread_mutex_lock(&surface_queue->lock);
1325
1326         if (_queue_is_empty(&surface_queue->free_queue)) {
1327                 if (surface_queue->impl && surface_queue->impl->need_attach)
1328                         surface_queue->impl->need_attach(surface_queue);
1329                 else
1330                         _tbm_surface_queue_need_attach(surface_queue);
1331         }
1332
1333         if (surface_queue->impl && surface_queue->impl->dequeue)
1334                 node = surface_queue->impl->dequeue(surface_queue);
1335         else
1336                 node = _tbm_surface_queue_dequeue(surface_queue);
1337
1338         if (node == NULL || node->surface == NULL) {
1339                 TBM_ERR("_queue_node_pop_front failed");
1340                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_EMPTY);
1341                 pthread_mutex_unlock(&surface_queue->lock);
1342
1343                 _tbm_surf_queue_mutex_unlock();
1344                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1345         }
1346
1347         node->type = QUEUE_NODE_TYPE_DEQUEUE;
1348         *surface = node->surface;
1349
1350         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, *surface);
1351
1352         pthread_mutex_unlock(&surface_queue->lock);
1353
1354         _tbm_surf_queue_mutex_unlock();
1355
1356         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1357
1358         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1359
1360         return TBM_SURFACE_QUEUE_ERROR_NONE;
1361 }
1362
1363 tbm_surface_queue_error_e
1364 tbm_surface_queue_can_dequeue_wait_timeout(tbm_surface_queue_h surface_queue, int ms_timeout)
1365 {
1366         int ret;
1367         struct timespec tp;
1368
1369         _tbm_surf_queue_mutex_lock();
1370         _tbm_set_last_result(TBM_ERROR_NONE);
1371
1372         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1373                                                                           TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1374
1375         _tbm_surf_queue_mutex_unlock();
1376
1377         _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1378
1379         _tbm_surf_queue_mutex_lock();
1380
1381         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1382                                                                           TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1383
1384         pthread_mutex_lock(&surface_queue->lock);
1385
1386         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1387
1388         if (_queue_is_empty(&surface_queue->free_queue)) {
1389                 if (surface_queue->impl && surface_queue->impl->need_attach)
1390                         surface_queue->impl->need_attach(surface_queue);
1391                 else
1392                         _tbm_surface_queue_need_attach(surface_queue);
1393         }
1394
1395         if (!_queue_is_empty(&surface_queue->free_queue)) {
1396                 pthread_mutex_unlock(&surface_queue->lock);
1397                 _tbm_surf_queue_mutex_unlock();
1398                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1399         }
1400
1401         _tbm_surf_queue_mutex_unlock();
1402
1403         while (1) {
1404                 clock_gettime(CLOCK_MONOTONIC, &tp);
1405
1406                 if (ms_timeout >= 1000)
1407                         tp.tv_sec += ms_timeout / 1000;
1408
1409                 tp.tv_nsec += (ms_timeout % 1000) * 1000000;
1410
1411                 if (tp.tv_nsec > 1000000000L) {
1412                         tp.tv_sec++;
1413                         tp.tv_nsec -= 1000000000L;
1414                 }
1415
1416                 ret = pthread_cond_timedwait(&surface_queue->free_cond, &surface_queue->lock, &tp);
1417                 if (ret) {
1418                         if (ret == ETIMEDOUT) {
1419                                 TBM_ERR("surface_queue:%p can dequeue wait timeout", surface_queue);
1420                                 pthread_mutex_unlock(&surface_queue->lock);
1421                                 return TBM_SURFACE_QUEUE_ERROR_TIMEOUT;
1422                         } else {
1423                                 TBM_INFO("surface_queue:%p timedwait error retry wait", surface_queue);
1424                         }
1425                 } else {
1426                         if (surface_queue->impl && surface_queue->impl->need_attach)
1427                                 surface_queue->impl->need_attach(surface_queue);
1428                         else
1429                                 _tbm_surface_queue_need_attach(surface_queue);
1430
1431                         if (!_queue_is_empty(&surface_queue->free_queue)) {
1432                                 pthread_mutex_unlock(&surface_queue->lock);
1433                                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1434                         }
1435                 }
1436         }
1437 }
1438
1439 int
1440 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1441 {
1442         _tbm_surf_queue_mutex_lock();
1443         _tbm_set_last_result(TBM_ERROR_NONE);
1444
1445         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1446
1447         _tbm_surf_queue_mutex_unlock();
1448
1449         _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1450
1451         _tbm_surf_queue_mutex_lock();
1452
1453         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1454
1455         pthread_mutex_lock(&surface_queue->lock);
1456
1457         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1458
1459         if (_queue_is_empty(&surface_queue->free_queue)) {
1460                 if (surface_queue->impl && surface_queue->impl->need_attach)
1461                         surface_queue->impl->need_attach(surface_queue);
1462                 else
1463                         _tbm_surface_queue_need_attach(surface_queue);
1464         }
1465
1466         if (!_queue_is_empty(&surface_queue->free_queue)) {
1467                 pthread_mutex_unlock(&surface_queue->lock);
1468                 _tbm_surf_queue_mutex_unlock();
1469                 return 1;
1470         }
1471
1472         if (wait) {
1473                 _tbm_surf_queue_mutex_unlock();
1474                 while (1) {
1475                         pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1476
1477                         if (surface_queue->impl && surface_queue->impl->need_attach)
1478                                 surface_queue->impl->need_attach(surface_queue);
1479                         else
1480                                 _tbm_surface_queue_need_attach(surface_queue);
1481
1482                         if (!_queue_is_empty(&surface_queue->free_queue)) {
1483                                 pthread_mutex_unlock(&surface_queue->lock);
1484                                 return 1;
1485                         }
1486                 }
1487         }
1488
1489         pthread_mutex_unlock(&surface_queue->lock);
1490         _tbm_surf_queue_mutex_unlock();
1491         return 0;
1492 }
1493
1494 tbm_surface_queue_error_e
1495 tbm_surface_queue_release(tbm_surface_queue_h
1496                           surface_queue, tbm_surface_h surface)
1497 {
1498         queue_node *node;
1499         int queue_type;
1500
1501         _tbm_surf_queue_mutex_lock();
1502         _tbm_set_last_result(TBM_ERROR_NONE);
1503
1504         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1505                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1506         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1507                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1508
1509         pthread_mutex_lock(&surface_queue->lock);
1510
1511         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, surface);
1512
1513         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1514         if (node == NULL || queue_type != NODE_LIST) {
1515                 TBM_ERR("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d",
1516                         node, queue_type);
1517                 pthread_mutex_unlock(&surface_queue->lock);
1518
1519                 _tbm_surf_queue_mutex_unlock();
1520
1521                 if (!node) {
1522                         _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE);
1523                         return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1524                 } else {
1525                         _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST);
1526                         return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1527                 }
1528         }
1529
1530         if (node->delete_pending) {
1531                 TBM_TRACE_SURFACE_QUEUE("delete pending tbm_surface_queue(%p) surface(%p)", surface_queue, node->surface);
1532
1533                 _queue_delete_node(surface_queue, node);
1534
1535                 pthread_mutex_unlock(&surface_queue->lock);
1536
1537                 _tbm_surf_queue_mutex_unlock();
1538
1539                 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1540
1541                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1542         }
1543
1544         if (surface_queue->queue_size < surface_queue->num_attached) {
1545                 TBM_TRACE_SURFACE_QUEUE("deatch tbm_surface_queue(%p) surface(%p)", surface_queue, node->surface);
1546
1547                 if (surface_queue->impl && surface_queue->impl->need_detach)
1548                         surface_queue->impl->need_detach(surface_queue, node);
1549                 else
1550                         _tbm_surface_queue_detach(surface_queue, surface);
1551
1552                 pthread_mutex_unlock(&surface_queue->lock);
1553
1554                 _tbm_surf_queue_mutex_unlock();
1555
1556                 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1557
1558                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1559         }
1560
1561         if (surface_queue->impl && surface_queue->impl->release)
1562                 surface_queue->impl->release(surface_queue, node);
1563         else
1564                 _tbm_surface_queue_release(surface_queue, node, 1);
1565
1566         if (!_queue_get_node(surface_queue, FREE_QUEUE, surface, NULL)) {
1567                 TBM_ERR("release surface(%p) but surface isn't present in the free_queue", surface);
1568                 _tbm_set_last_result(TBM_SURFACE_ERROR_INVALID_OPERATION);
1569                 pthread_mutex_unlock(&surface_queue->lock);
1570
1571                 _tbm_surf_queue_mutex_unlock();
1572                 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1573         }
1574
1575         node->type = QUEUE_NODE_TYPE_RELEASE;
1576
1577         pthread_mutex_unlock(&surface_queue->lock);
1578         pthread_cond_signal(&surface_queue->free_cond);
1579
1580         _tbm_surf_queue_mutex_unlock();
1581
1582         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1583
1584         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1585
1586         return TBM_SURFACE_QUEUE_ERROR_NONE;
1587 }
1588
1589 tbm_surface_queue_error_e
1590 tbm_surface_queue_cancel_acquire(tbm_surface_queue_h
1591                         surface_queue, tbm_surface_h surface)
1592 {
1593         queue_node *node;
1594         int queue_type;
1595
1596         _tbm_surf_queue_mutex_lock();
1597         _tbm_set_last_result(TBM_ERROR_NONE);
1598
1599         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1600                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1601         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1602                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1603
1604         pthread_mutex_lock(&surface_queue->lock);
1605
1606         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, surface);
1607
1608         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1609         if (node == NULL || queue_type != NODE_LIST) {
1610                 TBM_ERR("tbm_surface_queue_cancel_acquire::Surface is existed in free_queue or dirty_queue node:%p, type:%d",
1611                         node, queue_type);
1612                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST);
1613                 pthread_mutex_unlock(&surface_queue->lock);
1614
1615                 _tbm_surf_queue_mutex_unlock();
1616                 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1617         }
1618
1619         if (surface_queue->impl && surface_queue->impl->enqueue)
1620                 surface_queue->impl->enqueue(surface_queue, node);
1621         else
1622                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1623
1624         if (_queue_is_empty(&surface_queue->dirty_queue)) {
1625                 TBM_ERR("enqueue surface but queue is empty node:%p", node);
1626                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE);
1627                 pthread_mutex_unlock(&surface_queue->lock);
1628
1629                 _tbm_surf_queue_mutex_unlock();
1630                 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1631         }
1632
1633         node->type = QUEUE_NODE_TYPE_ENQUEUE;
1634
1635         pthread_mutex_unlock(&surface_queue->lock);
1636         pthread_cond_signal(&surface_queue->dirty_cond);
1637
1638         _tbm_surf_queue_mutex_unlock();
1639
1640         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_ACQUIRE);
1641
1642         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1643
1644         return TBM_SURFACE_QUEUE_ERROR_NONE;
1645 }
1646
1647 tbm_surface_queue_error_e
1648 tbm_surface_queue_acquire(tbm_surface_queue_h
1649                           surface_queue, tbm_surface_h *surface)
1650 {
1651         queue_node *node;
1652
1653         _tbm_surf_queue_mutex_lock();
1654         _tbm_set_last_result(TBM_ERROR_NONE);
1655
1656         *surface = NULL;
1657
1658         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1659                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1660         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1661                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1662
1663         pthread_mutex_lock(&surface_queue->lock);
1664
1665         if (surface_queue->impl && surface_queue->impl->acquire)
1666                 node = surface_queue->impl->acquire(surface_queue);
1667         else
1668                 node = _tbm_surface_queue_acquire(surface_queue);
1669
1670         if (node == NULL || node->surface == NULL) {
1671                 TBM_ERR("_queue_node_pop_front failed");
1672                 _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_EMPTY);
1673                 pthread_mutex_unlock(&surface_queue->lock);
1674
1675                 _tbm_surf_queue_mutex_unlock();
1676                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1677         }
1678
1679         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1680
1681         *surface = node->surface;
1682
1683         if (surface_queue->acquire_sync_count == 1) {
1684                 tbm_surface_info_s info;
1685                 int ret;
1686
1687                 TBM_ERR("start map surface:%p", *surface);
1688                 ret = tbm_surface_map(*surface, TBM_SURF_OPTION_READ, &info);
1689                 TBM_ERR("end map surface:%p", *surface);
1690                 if (ret == TBM_SURFACE_ERROR_NONE)
1691                         tbm_surface_unmap(*surface);
1692         }
1693
1694         if (surface_queue->acquire_sync_count > 0) surface_queue->acquire_sync_count--;
1695
1696         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)", surface_queue, *surface);
1697
1698         pthread_mutex_unlock(&surface_queue->lock);
1699
1700         _tbm_surf_queue_mutex_unlock();
1701
1702         if (b_dump_queue)
1703                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1704
1705         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1706
1707         return TBM_SURFACE_QUEUE_ERROR_NONE;
1708 }
1709
1710 int
1711 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1712 {
1713         _tbm_surf_queue_mutex_lock();
1714         _tbm_set_last_result(TBM_ERROR_NONE);
1715
1716         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1717
1718         pthread_mutex_lock(&surface_queue->lock);
1719
1720         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1721
1722         if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1723                 pthread_mutex_unlock(&surface_queue->lock);
1724                 _tbm_surf_queue_mutex_unlock();
1725                 return 1;
1726         }
1727
1728         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1729                                                 QUEUE_NODE_TYPE_DEQUEUE)) {
1730                 _tbm_surf_queue_mutex_unlock();
1731                 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1732                 pthread_mutex_unlock(&surface_queue->lock);
1733                 return 1;
1734         }
1735
1736         pthread_mutex_unlock(&surface_queue->lock);
1737         _tbm_surf_queue_mutex_unlock();
1738         return 0;
1739 }
1740
1741 void
1742 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1743 {
1744         queue_node *node = NULL, *tmp;
1745
1746         _tbm_surf_queue_mutex_lock();
1747         _tbm_set_last_result(TBM_ERROR_NONE);
1748
1749         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1750
1751         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1752
1753         surface_queue->magic = 0;
1754
1755         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1756                 _queue_delete_node(surface_queue, node);
1757
1758         if (surface_queue->impl && surface_queue->impl->destroy)
1759                 surface_queue->impl->destroy(surface_queue);
1760
1761         _notify_emit(surface_queue, &surface_queue->destory_noti);
1762
1763         _notify_remove_all(&surface_queue->destory_noti);
1764         _notify_remove_all(&surface_queue->dequeuable_noti);
1765         _notify_remove_all(&surface_queue->dequeue_noti);
1766         _notify_remove_all(&surface_queue->can_dequeue_noti);
1767         _notify_remove_all(&surface_queue->acquirable_noti);
1768         _notify_remove_all(&surface_queue->reset_noti);
1769         _trace_remove_all(&surface_queue->trace_noti);
1770
1771         pthread_mutex_destroy(&surface_queue->lock);
1772
1773         free(surface_queue);
1774
1775         _tbm_surf_queue_mutex_unlock();
1776 }
1777
1778 tbm_surface_queue_error_e
1779 tbm_surface_queue_reset(tbm_surface_queue_h
1780                         surface_queue, int width, int height, int format)
1781 {
1782         queue_node *node = NULL, *tmp;
1783
1784         _tbm_surf_queue_mutex_lock();
1785         _tbm_set_last_result(TBM_ERROR_NONE);
1786
1787         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1788                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1789
1790         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1791
1792         pthread_mutex_lock(&surface_queue->lock);
1793
1794         if (width == surface_queue->width && height == surface_queue->height &&
1795                 format == surface_queue->format) {
1796                 pthread_mutex_unlock(&surface_queue->lock);
1797                 _tbm_surf_queue_mutex_unlock();
1798                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1799         }
1800
1801         surface_queue->width = width;
1802         surface_queue->height = height;
1803         surface_queue->format = format;
1804
1805         if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1806                 /* Destory surface and Push to free_queue */
1807                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1808                         _queue_delete_node(surface_queue, node);
1809
1810                 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1811                         node->delete_pending = 1;
1812         } else {
1813                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1814                         _queue_delete_node(surface_queue, node);
1815
1816                 _queue_init(&surface_queue->dirty_queue);
1817                 LIST_INITHEAD(&surface_queue->list);
1818         }
1819
1820         /* Reset queue */
1821         _queue_init(&surface_queue->free_queue);
1822
1823         surface_queue->num_attached = 0;
1824
1825         if (surface_queue->impl && surface_queue->impl->reset)
1826                 surface_queue->impl->reset(surface_queue);
1827
1828         pthread_mutex_unlock(&surface_queue->lock);
1829         pthread_cond_signal(&surface_queue->free_cond);
1830
1831         _tbm_surf_queue_mutex_unlock();
1832
1833         _notify_emit(surface_queue, &surface_queue->reset_noti);
1834
1835         return TBM_SURFACE_QUEUE_ERROR_NONE;
1836 }
1837
1838 tbm_surface_queue_error_e
1839 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1840 {
1841         _tbm_surf_queue_mutex_lock();
1842         _tbm_set_last_result(TBM_ERROR_NONE);
1843
1844         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1845                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1846
1847         _tbm_surf_queue_mutex_unlock();
1848
1849         _notify_emit(surface_queue, &surface_queue->reset_noti);
1850
1851         return TBM_SURFACE_QUEUE_ERROR_NONE;
1852 }
1853
1854 tbm_surface_queue_error_e
1855 tbm_surface_queue_notify_dequeuable(tbm_surface_queue_h surface_queue)
1856 {
1857         _tbm_surf_queue_mutex_lock();
1858         _tbm_set_last_result(TBM_ERROR_NONE);
1859
1860         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1861                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1862
1863         pthread_mutex_lock(&surface_queue->lock);
1864         pthread_mutex_unlock(&surface_queue->lock);
1865         pthread_cond_signal(&surface_queue->free_cond);
1866
1867         _tbm_surf_queue_mutex_unlock();
1868
1869         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1870
1871         return TBM_SURFACE_QUEUE_ERROR_NONE;
1872 }
1873
1874 tbm_surface_queue_error_e
1875 tbm_surface_queue_set_size(tbm_surface_queue_h
1876                         surface_queue, int queue_size, int flush)
1877 {
1878         queue_node *node = NULL, *tmp;
1879
1880         _tbm_surf_queue_mutex_lock();
1881         _tbm_set_last_result(TBM_ERROR_NONE);
1882
1883         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1884                                         TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1885         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1886                                         TBM_ERROR_INVALID_PARAMETER);
1887
1888         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1889
1890         if ((surface_queue->queue_size == queue_size) && !flush) {
1891                 _tbm_surf_queue_mutex_unlock();
1892                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1893         }
1894
1895         pthread_mutex_lock(&surface_queue->lock);
1896
1897         if (flush) {
1898                 surface_queue->queue_size = queue_size;
1899
1900                 if (surface_queue->num_attached == 0) {
1901                         pthread_mutex_unlock(&surface_queue->lock);
1902                         _tbm_surf_queue_mutex_unlock();
1903                         return TBM_SURFACE_QUEUE_ERROR_NONE;
1904                 }
1905
1906                 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1907                         /* Destory surface and Push to free_queue */
1908                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1909                                 _queue_delete_node(surface_queue, node);
1910
1911                         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1912                                 node->delete_pending = 1;
1913                 } else {
1914                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1915                                 _queue_delete_node(surface_queue, node);
1916
1917                         _queue_init(&surface_queue->dirty_queue);
1918                         LIST_INITHEAD(&surface_queue->list);
1919                 }
1920
1921                 /* Reset queue */
1922                 _queue_init(&surface_queue->free_queue);
1923
1924                 surface_queue->num_attached = 0;
1925
1926                 if (surface_queue->impl && surface_queue->impl->reset)
1927                         surface_queue->impl->reset(surface_queue);
1928
1929                 pthread_mutex_unlock(&surface_queue->lock);
1930                 pthread_cond_signal(&surface_queue->free_cond);
1931
1932                 _tbm_surf_queue_mutex_unlock();
1933
1934                 _notify_emit(surface_queue, &surface_queue->reset_noti);
1935
1936                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1937         } else {
1938                 if (surface_queue->queue_size > queue_size) {
1939                         int need_del = surface_queue->queue_size - queue_size;
1940
1941                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1942                                 TBM_TRACE_SURFACE_QUEUE("deatch tbm_surface_queue(%p) surface(%p)", surface_queue, node->surface);
1943
1944                                 if (surface_queue->impl && surface_queue->impl->need_detach)
1945                                         surface_queue->impl->need_detach(surface_queue, node);
1946                                 else
1947                                         _tbm_surface_queue_detach(surface_queue, node->surface);
1948
1949                                 need_del--;
1950                                 if (need_del == 0)
1951                                         break;
1952                         }
1953                 }
1954
1955                 surface_queue->queue_size = queue_size;
1956
1957                 pthread_mutex_unlock(&surface_queue->lock);
1958
1959                 _tbm_surf_queue_mutex_unlock();
1960
1961                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1962         }
1963 }
1964
1965 tbm_surface_queue_error_e
1966 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1967 {
1968         queue_node *node = NULL;
1969         int is_guarantee_cycle = 0;
1970
1971         _tbm_surf_queue_mutex_lock();
1972         _tbm_set_last_result(TBM_ERROR_NONE);
1973
1974         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1975                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1976
1977         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
1978
1979         if (surface_queue->num_attached == 0) {
1980                 _tbm_surf_queue_mutex_unlock();
1981                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1982         }
1983
1984         pthread_mutex_lock(&surface_queue->lock);
1985
1986         /* Destory surface in free_queue */
1987         while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1988                 if (surface_queue->impl && surface_queue->impl->need_detach)
1989                         surface_queue->impl->need_detach(surface_queue, node);
1990                 else
1991                         _tbm_surface_queue_detach(surface_queue, node->surface);
1992         }
1993
1994         /* Reset queue */
1995         _queue_init(&surface_queue->free_queue);
1996
1997         if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE)
1998                 is_guarantee_cycle = 1;
1999
2000         pthread_mutex_unlock(&surface_queue->lock);
2001         _tbm_surf_queue_mutex_unlock();
2002
2003         if (is_guarantee_cycle)
2004                 _notify_emit(surface_queue, &surface_queue->reset_noti);
2005
2006         return TBM_SURFACE_QUEUE_ERROR_NONE;
2007 }
2008
2009 tbm_surface_queue_error_e
2010 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
2011 {
2012         queue_node *node = NULL, *tmp;
2013
2014         _tbm_surf_queue_mutex_lock();
2015         _tbm_set_last_result(TBM_ERROR_NONE);
2016
2017         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2018                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2019
2020         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
2021
2022         pthread_mutex_lock(&surface_queue->lock);
2023
2024         if (surface_queue->num_attached == 0) {
2025                 pthread_mutex_unlock(&surface_queue->lock);
2026                 _tbm_surf_queue_mutex_unlock();
2027                 return TBM_SURFACE_QUEUE_ERROR_NONE;
2028         }
2029
2030         if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
2031                 /* Destory surface and Push to free_queue */
2032                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
2033                         _queue_delete_node(surface_queue, node);
2034
2035                 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
2036                         node->delete_pending = 1;
2037         } else {
2038                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
2039                         _queue_delete_node(surface_queue, node);
2040
2041                 _queue_init(&surface_queue->dirty_queue);
2042                 LIST_INITHEAD(&surface_queue->list);
2043         }
2044
2045         /* Reset queue */
2046         _queue_init(&surface_queue->free_queue);
2047
2048         surface_queue->num_attached = 0;
2049
2050         if (surface_queue->impl && surface_queue->impl->reset)
2051                 surface_queue->impl->reset(surface_queue);
2052
2053         pthread_mutex_unlock(&surface_queue->lock);
2054         pthread_cond_signal(&surface_queue->free_cond);
2055
2056         _tbm_surf_queue_mutex_unlock();
2057
2058         _notify_emit(surface_queue, &surface_queue->reset_noti);
2059
2060         return TBM_SURFACE_QUEUE_ERROR_NONE;
2061 }
2062
2063 tbm_surface_queue_error_e
2064 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
2065                         tbm_surface_h *surfaces, int *num)
2066 {
2067         queue_node *node = NULL;
2068
2069         _tbm_surf_queue_mutex_lock();
2070         _tbm_set_last_result(TBM_ERROR_NONE);
2071
2072         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2073                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2074         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
2075                                TBM_ERROR_INVALID_PARAMETER);
2076
2077         *num = 0;
2078
2079         pthread_mutex_lock(&surface_queue->lock);
2080
2081         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
2082                 if (node->delete_pending) continue;
2083
2084                 if (surfaces)
2085                         surfaces[*num] = node->surface;
2086
2087                 *num = *num + 1;
2088         }
2089
2090         pthread_mutex_unlock(&surface_queue->lock);
2091
2092         _tbm_surf_queue_mutex_unlock();
2093
2094         return TBM_SURFACE_QUEUE_ERROR_NONE;
2095 }
2096
2097 tbm_surface_queue_error_e
2098 tbm_surface_queue_get_acquirable_surfaces(tbm_surface_queue_h surface_queue,
2099                         tbm_surface_h *surfaces, int *num)
2100 {
2101         queue_node *node = NULL;
2102
2103         _tbm_surf_queue_mutex_lock();
2104
2105         *num = 0;
2106
2107         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2108                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2109         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
2110                                TBM_ERROR_INVALID_PARAMETER);
2111
2112         pthread_mutex_lock(&surface_queue->lock);
2113
2114         LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head, item_link) {
2115                 if (surfaces)
2116                         surfaces[*num] = node->surface;
2117
2118                 *num = *num + 1;
2119         }
2120
2121         pthread_mutex_unlock(&surface_queue->lock);
2122
2123         _tbm_surf_queue_mutex_unlock();
2124
2125         return TBM_SURFACE_QUEUE_ERROR_NONE;
2126 }
2127
2128 tbm_surface_queue_error_e
2129 tbm_surface_queue_get_trace_surface_num(
2130                         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
2131 {
2132         _tbm_surf_queue_mutex_lock();
2133         _tbm_set_last_result(TBM_ERROR_NONE);
2134
2135         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2136                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2137         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
2138                                TBM_ERROR_INVALID_PARAMETER);
2139
2140         *num = 0;
2141
2142         pthread_mutex_lock(&surface_queue->lock);
2143
2144         switch (trace) {
2145         case TBM_SURFACE_QUEUE_TRACE_NONE:
2146                 *num = 0;
2147                 break;
2148         case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
2149                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
2150                 break;
2151         case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
2152                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
2153                 break;
2154         case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
2155                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
2156                 break;
2157         case TBM_SURFACE_QUEUE_TRACE_RELEASE:
2158                 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
2159                 break;
2160         default:
2161                 break;
2162         }
2163
2164         pthread_mutex_unlock(&surface_queue->lock);
2165
2166         _tbm_surf_queue_mutex_unlock();
2167
2168         return TBM_SURFACE_QUEUE_ERROR_NONE;
2169 }
2170
2171 static const tbm_surface_queue_interface tbm_queue_default_impl = {
2172         NULL,                           /*__tbm_queue_default_init*/
2173         NULL,                           /*__tbm_queue_default_reset*/
2174         NULL,                           /*__tbm_queue_default_destroy*/
2175         NULL,                           /*__tbm_queue_default_need_attach*/
2176         NULL,                           /*__tbm_queue_default_enqueue*/
2177         NULL,                           /*__tbm_queue_default_release*/
2178         NULL,                           /*__tbm_queue_default_dequeue*/
2179         NULL,                           /*__tbm_queue_default_acquire*/
2180         NULL,                           /*__tbm_queue_default_need_detach*/
2181 };
2182
2183 tbm_surface_queue_h
2184 tbm_surface_queue_create(int queue_size, int width,
2185                          int height, int format, int flags)
2186 {
2187         _tbm_surf_queue_mutex_lock();
2188         _tbm_set_last_result(TBM_ERROR_NONE);
2189
2190         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
2191         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(width > 0, NULL);
2192         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(height > 0, NULL);
2193         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(format > 0, NULL);
2194
2195         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
2196                                             sizeof(struct _tbm_surface_queue));
2197         if (!surface_queue) {
2198                 TBM_ERR("cannot allocate the surface_queue.");
2199                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2200                 _tbm_surf_queue_mutex_unlock();
2201                 return NULL;
2202         }
2203
2204         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
2205
2206         _tbm_surface_queue_init(surface_queue,
2207                                 queue_size,
2208                                 width, height, format, flags,
2209                                 &tbm_queue_default_impl, NULL);
2210
2211         _tbm_surf_queue_mutex_unlock();
2212
2213         return surface_queue;
2214 }
2215
2216 typedef struct {
2217         queue dequeue_list;
2218 } tbm_queue_sequence;
2219
2220 static void
2221 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
2222 {
2223         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2224
2225         _queue_init(&data->dequeue_list);
2226 }
2227
2228 static void
2229 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
2230 {
2231         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2232
2233         if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE)
2234                 return;
2235
2236         _queue_init(&data->dequeue_list);
2237 }
2238
2239 static void
2240 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
2241 {
2242         free(surface_queue->impl_data);
2243 }
2244
2245 static void
2246 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
2247                              queue_node *node)
2248 {
2249         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2250         queue_node *first = NULL;
2251
2252         first = container_of(data->dequeue_list.head.next, first, item_link);
2253         if (first != node) {
2254                 return;
2255         }
2256
2257         node->priv_flags = 0;
2258
2259         _queue_node_pop(&data->dequeue_list, node);
2260         _tbm_surface_queue_enqueue(surface_queue, node, 1);
2261 }
2262
2263 static void
2264 __tbm_queue_sequence_release(tbm_surface_queue_h surface_queue,
2265                                 queue_node *node)
2266 {
2267         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2268
2269         if (node->priv_flags) {
2270                 node->priv_flags = 0;
2271                 _queue_node_pop(&data->dequeue_list, node);
2272         }
2273
2274         _tbm_surface_queue_release(surface_queue, node, 1);
2275 }
2276
2277 static queue_node *
2278 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
2279                              surface_queue)
2280 {
2281         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2282         queue_node *node;
2283
2284         node = _tbm_surface_queue_dequeue(surface_queue);
2285         if (node) {
2286                 _queue_node_push_back(&data->dequeue_list, node);
2287                 node->priv_flags = 1;
2288         }
2289
2290         return node;
2291 }
2292
2293 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
2294         __tbm_queue_sequence_init,
2295         __tbm_queue_sequence_reset,
2296         __tbm_queue_sequence_destroy,
2297         NULL,
2298         __tbm_queue_sequence_enqueue,
2299         __tbm_queue_sequence_release,
2300         __tbm_queue_sequence_dequeue,
2301         NULL,                                   /*__tbm_queue_sequence_acquire*/
2302         NULL,                                   /*__tbm_queue_sequence_need_dettach*/
2303 };
2304
2305 tbm_surface_queue_h
2306 tbm_surface_queue_sequence_create(int queue_size, int width,
2307                                   int height, int format, int flags)
2308 {
2309         _tbm_surf_queue_mutex_lock();
2310         _tbm_set_last_result(TBM_ERROR_NONE);
2311
2312         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
2313         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(width > 0, NULL);
2314         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(height > 0, NULL);
2315         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(format > 0, NULL);
2316
2317         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
2318                                             sizeof(struct _tbm_surface_queue));
2319         if (surface_queue == NULL) {
2320                 TBM_ERR("cannot allocate the surface_queue.");
2321                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2322                 _tbm_surf_queue_mutex_unlock();
2323                 return NULL;
2324         }
2325
2326         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)", surface_queue);
2327
2328         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
2329                                    sizeof(tbm_queue_sequence));
2330         if (data == NULL) {
2331                 TBM_ERR("cannot allocate the tbm_queue_sequence.");
2332                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2333                 free(surface_queue);
2334                 _tbm_surf_queue_mutex_unlock();
2335                 return NULL;
2336         }
2337
2338         _tbm_surface_queue_init(surface_queue,
2339                                 queue_size,
2340                                 width, height, format, flags,
2341                                 &tbm_queue_sequence_impl, data);
2342
2343         _tbm_surf_queue_mutex_unlock();
2344
2345         return surface_queue;
2346 }
2347
2348 tbm_surface_queue_error_e
2349 tbm_surface_queue_set_modes(tbm_surface_queue_h surface_queue,
2350                                   int modes)
2351 {
2352         _tbm_surf_queue_mutex_lock();
2353         _tbm_set_last_result(TBM_ERROR_NONE);
2354
2355         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2356                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2357
2358         pthread_mutex_lock(&surface_queue->lock);
2359
2360         if (modes == TBM_SURFACE_QUEUE_MODE_NONE)
2361                 modes = TBM_SURFACE_QUEUE_MODE_NONE;
2362         else
2363                 surface_queue->modes |= modes;
2364
2365         pthread_mutex_unlock(&surface_queue->lock);
2366
2367         _tbm_surf_queue_mutex_unlock();
2368
2369         return TBM_SURFACE_QUEUE_ERROR_NONE;
2370 }
2371
2372 tbm_surface_queue_error_e
2373 tbm_surface_queue_set_sync_count(tbm_surface_queue_h surface_queue,
2374                                   unsigned int sync_count)
2375 {
2376         int dequeue_num, enqueue_num;
2377
2378         _tbm_surf_queue_mutex_lock();
2379         _tbm_set_last_result(TBM_ERROR_NONE);
2380
2381         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2382                                    TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2383
2384         pthread_mutex_lock(&surface_queue->lock);
2385
2386         dequeue_num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
2387         enqueue_num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
2388
2389         if (dequeue_num + sync_count == 0)
2390                 surface_queue->acquire_sync_count = enqueue_num;
2391         else
2392                 surface_queue->enqueue_sync_count = dequeue_num + sync_count;
2393
2394         TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) enqueue_sync_count:(%d) acquire_sync_count:(%d)",
2395                                 surface_queue, surface_queue->enqueue_sync_count, surface_queue->acquire_sync_count);
2396
2397         pthread_mutex_unlock(&surface_queue->lock);
2398
2399         _tbm_surf_queue_mutex_unlock();
2400
2401         return TBM_SURFACE_QUEUE_ERROR_NONE;
2402 }