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