use TBM_LOG_E at error case in tbm_surface_queue.c
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include "tbm_bufmgr_int.h"
35 #include "list.h"
36
37 #define FREE_QUEUE      1
38 #define DIRTY_QUEUE     2
39 #define NODE_LIST       4
40
41 #define TBM_QUEUE_DEBUG 0
42
43 #ifdef TRACE
44 #define TBM_QUEUE_TRACE(fmt, ...)  { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
45 #else
46 #define TBM_QUEUE_TRACE(fmt, ...)
47 #endif /* TRACE */
48
49 #if TBM_QUEUE_DEBUG
50 #define TBM_LOCK() TBM_LOG_D("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
51 #define TBM_UNLOCK() TBM_LOG_D("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
52 #else
53 #define TBM_LOCK()
54 #define TBM_UNLOCK()
55 #endif
56
57 static tbm_bufmgr g_surf_queue_bufmgr;
58 static pthread_mutex_t tbm_surf_queue_lock;
59 void _tbm_surface_queue_mutex_unlock(void);
60
61 /* check condition */
62 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
63         if (!(cond)) {\
64                 TBM_LOG_E("'%s' failed.\n", #cond);\
65                 _tbm_surf_queue_mutex_unlock();\
66                 return;\
67         } \
68 }
69
70 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
71         if (!(cond)) {\
72                 TBM_LOG_E("'%s' failed.\n", #cond);\
73                 _tbm_surf_queue_mutex_unlock();\
74                 return val;\
75         } \
76 }
77
78 typedef enum _queue_node_type {
79         QUEUE_NODE_TYPE_NONE,
80         QUEUE_NODE_TYPE_DEQUEUE,
81         QUEUE_NODE_TYPE_ENQUEUE,
82         QUEUE_NODE_TYPE_ACQUIRE,
83         QUEUE_NODE_TYPE_RELEASE
84 } Queue_Node_Type;
85
86 typedef struct {
87         struct list_head head;
88         int count;
89 } queue;
90
91 typedef struct {
92         tbm_surface_h surface;
93
94         struct list_head item_link;
95         struct list_head link;
96
97         Queue_Node_Type type;
98
99         unsigned int priv_flags;        /*for each queue*/
100 } queue_node;
101
102 typedef struct {
103         struct list_head link;
104
105         tbm_surface_queue_notify_cb cb;
106         void *data;
107 } queue_notify;
108
109 typedef struct {
110         struct list_head link;
111
112         tbm_surface_queue_trace_cb cb;
113         void *data;
114 } queue_trace;
115
116 typedef struct _tbm_surface_queue_interface {
117         void (*init)(tbm_surface_queue_h queue);
118         void (*reset)(tbm_surface_queue_h queue);
119         void (*destroy)(tbm_surface_queue_h queue);
120         void (*need_attach)(tbm_surface_queue_h queue);
121
122         void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
123         void (*release)(tbm_surface_queue_h queue, queue_node *node);
124         queue_node *(*dequeue)(tbm_surface_queue_h queue);
125         queue_node *(*acquire)(tbm_surface_queue_h queue);
126         void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
127 } tbm_surface_queue_interface;
128
129 struct _tbm_surface_queue {
130         int width;
131         int height;
132         int format;
133         int queue_size;
134         int num_attached;
135
136         queue free_queue;
137         queue dirty_queue;
138         struct list_head list;
139
140         struct list_head destory_noti;
141         struct list_head dequeuable_noti;
142         struct list_head dequeue_noti;
143         struct list_head can_dequeue_noti;
144         struct list_head acquirable_noti;
145         struct list_head reset_noti;
146         struct list_head trace_noti;
147
148         pthread_mutex_t lock;
149         pthread_cond_t free_cond;
150         pthread_cond_t dirty_cond;
151
152         const tbm_surface_queue_interface *impl;
153         void *impl_data;
154
155         //For external buffer allocation
156         tbm_surface_alloc_cb alloc_cb;
157         tbm_surface_free_cb free_cb;
158         void *alloc_cb_data;
159
160         struct list_head item_link; /* link of surface queue */
161 };
162
163 /* LCOV_EXCL_START */
164
165 static bool
166 _tbm_surf_queue_mutex_init(void)
167 {
168         static bool tbm_surf_queue_mutex_init = false;
169
170         if (tbm_surf_queue_mutex_init)
171                 return true;
172
173         if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
174                 TBM_LOG_E("fail: pthread_mutex_init\n");
175                 return false;
176         }
177
178         tbm_surf_queue_mutex_init = true;
179
180         return true;
181 }
182
183 static void
184 _tbm_surf_queue_mutex_lock(void)
185 {
186         if (!_tbm_surf_queue_mutex_init()) {
187                 TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n");
188                 return;
189         }
190
191         pthread_mutex_lock(&tbm_surf_queue_lock);
192 }
193
194 static void
195 _tbm_surf_queue_mutex_unlock(void)
196 {
197         pthread_mutex_unlock(&tbm_surf_queue_lock);
198 }
199
200 static void
201 _init_tbm_surf_queue_bufmgr(void)
202 {
203         g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
204 }
205
206 static void
207 _deinit_tbm_surf_queue_bufmgr(void)
208 {
209         if (!g_surf_queue_bufmgr)
210                 return;
211
212         tbm_bufmgr_deinit(g_surf_queue_bufmgr);
213         g_surf_queue_bufmgr = NULL;
214 }
215
216 static int
217 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
218 {
219         tbm_surface_queue_h old_data = NULL;
220
221         if (surface_queue == NULL) {
222                 TBM_LOG_E("error: surface_queue is NULL.\n");
223                 return 0;
224         }
225
226         if (g_surf_queue_bufmgr == NULL) {
227                 TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n");
228                 return 0;
229         }
230
231         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
232                 TBM_LOG_E("error: surf_queue_list is empty\n");
233                 return 0;
234         }
235
236         LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
237                                 item_link) {
238                 if (old_data == surface_queue) {
239                         TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
240                         return 1;
241                 }
242         }
243
244         TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
245
246         return 0;
247 }
248
249 static queue_node *
250 _queue_node_create(void)
251 {
252         queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
253
254         TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
255
256         return node;
257 }
258
259 static void
260 _queue_node_delete(queue_node *node)
261 {
262         LIST_DEL(&node->item_link);
263         LIST_DEL(&node->link);
264         free(node);
265 }
266
267 static int
268 _queue_is_empty(queue *queue)
269 {
270         if (LIST_IS_EMPTY(&queue->head))
271                 return 1;
272
273         return 0;
274 }
275
276 static void
277 _queue_node_push_back(queue *queue, queue_node *node)
278 {
279         LIST_ADDTAIL(&node->item_link, &queue->head);
280         queue->count++;
281 }
282
283 static void
284 _queue_node_push_front(queue *queue, queue_node *node)
285 {
286         LIST_ADD(&node->item_link, &queue->head);
287         queue->count++;
288 }
289
290 static queue_node *
291 _queue_node_pop_front(queue *queue)
292 {
293         queue_node *node;
294
295         node = LIST_ENTRY(queue_node, queue->head.next, item_link);
296
297         LIST_DEL(&node->item_link);
298         queue->count--;
299
300         return node;
301 }
302
303 static queue_node *
304 _queue_node_pop(queue *queue, queue_node *node)
305 {
306         LIST_DEL(&node->item_link);
307         queue->count--;
308
309         return node;
310 }
311
312 static queue_node *
313 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
314                 tbm_surface_h surface, int *out_type)
315 {
316         queue_node *node = NULL;
317
318         if (type == 0)
319                 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
320         if (out_type)
321                 *out_type = 0;
322
323         if (type & FREE_QUEUE) {
324                 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
325                                          item_link) {
326                         if (node->surface == surface) {
327                                 if (out_type)
328                                         *out_type = FREE_QUEUE;
329
330                                 return node;
331                         }
332                 }
333         }
334
335         if (type & DIRTY_QUEUE) {
336                 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
337                                          item_link) {
338                         if (node->surface == surface) {
339                                 if (out_type)
340                                         *out_type = DIRTY_QUEUE;
341
342                                 return node;
343                         }
344                 }
345         }
346
347         if (type & NODE_LIST) {
348                 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
349                         if (node->surface == surface) {
350                                 if (out_type)
351                                         *out_type = NODE_LIST;
352
353                                 return node;
354                         }
355                 }
356         }
357
358         TBM_LOG_E("fail to get the queue_node.\n");
359
360         return NULL;
361 }
362
363 static void
364 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
365 {
366         if (node->surface) {
367                 if (surface_queue->free_cb) {
368                         surface_queue->free_cb(surface_queue,
369                                         surface_queue->alloc_cb_data,
370                                         node->surface);
371                 }
372
373                 tbm_surface_destroy(node->surface);
374         }
375
376         _queue_node_delete(node);
377 }
378
379 static void
380 _queue_init(queue *queue)
381 {
382         LIST_INITHEAD(&queue->head);
383
384         queue->count = 0;
385 }
386
387 static void
388 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
389             void *data)
390 {
391         TBM_RETURN_IF_FAIL(cb != NULL);
392
393         queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
394
395         TBM_RETURN_IF_FAIL(item != NULL);
396
397         LIST_INITHEAD(&item->link);
398         item->cb = cb;
399         item->data = data;
400
401         LIST_ADDTAIL(&item->link, list);
402 }
403
404 static void
405 _notify_remove(struct list_head *list,
406                tbm_surface_queue_notify_cb cb, void *data)
407 {
408         queue_notify *item = NULL, *tmp;
409
410         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
411                 if (item->cb == cb && item->data == data) {
412                         LIST_DEL(&item->link);
413                         free(item);
414                         return;
415                 }
416         }
417
418         TBM_LOG_E("Cannot find notifiy\n");
419 }
420
421 static void
422 _notify_remove_all(struct list_head *list)
423 {
424         queue_notify *item = NULL, *tmp;
425
426         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
427                 LIST_DEL(&item->link);
428                 free(item);
429         }
430 }
431
432 static void
433 _notify_emit(tbm_surface_queue_h surface_queue,
434              struct list_head *list)
435 {
436         queue_notify *item = NULL, *tmp;;
437
438         /*
439                 The item->cb is the outside function of the libtbm.
440                 The tbm user may/can remove the item of the list,
441                 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
442         */
443         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
444                 item->cb(surface_queue, item->data);
445 }
446
447 static void
448 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
449             void *data)
450 {
451         TBM_RETURN_IF_FAIL(cb != NULL);
452
453         queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
454
455         TBM_RETURN_IF_FAIL(item != NULL);
456
457         LIST_INITHEAD(&item->link);
458         item->cb = cb;
459         item->data = data;
460
461         LIST_ADDTAIL(&item->link, list);
462 }
463
464 static void
465 _trace_remove(struct list_head *list,
466                tbm_surface_queue_trace_cb cb, void *data)
467 {
468         queue_trace *item = NULL, *tmp;
469
470         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
471                 if (item->cb == cb && item->data == data) {
472                         LIST_DEL(&item->link);
473                         free(item);
474                         return;
475                 }
476         }
477
478         TBM_LOG_E("Cannot find notifiy\n");
479 }
480
481 static void
482 _trace_remove_all(struct list_head *list)
483 {
484         queue_trace *item = NULL, *tmp;
485
486         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
487                 LIST_DEL(&item->link);
488                 free(item);
489         }
490 }
491
492 static void
493 _trace_emit(tbm_surface_queue_h surface_queue,
494              struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
495 {
496         queue_trace *item = NULL, *tmp;;
497
498         /*
499                 The item->cb is the outside function of the libtbm.
500                 The tbm user may/can remove the item of the list,
501                 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
502         */
503         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
504                 item->cb(surface_queue, surface, trace, item->data);
505 }
506
507 static int
508 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
509 {
510         queue_node *node = NULL;
511         int count = 0;
512
513         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
514                 if (node->type == type)
515                         count++;
516         }
517
518         return count;
519 }
520
521 static void
522 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
523                           tbm_surface_h surface)
524 {
525         queue_node *node;
526
527         node = _queue_node_create();
528         TBM_RETURN_IF_FAIL(node != NULL);
529
530         tbm_surface_internal_ref(surface);
531         node->surface = surface;
532
533         LIST_ADDTAIL(&node->link, &surface_queue->list);
534         surface_queue->num_attached++;
535         _queue_node_push_back(&surface_queue->free_queue, node);
536 }
537
538 static void
539 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
540                           tbm_surface_h surface)
541 {
542         queue_node *node;
543         int queue_type;
544
545         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
546         if (node) {
547                 _queue_delete_node(surface_queue, node);
548                 surface_queue->num_attached--;
549         }
550 }
551
552 static void
553 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
554                            queue_node *node, int push_back)
555 {
556         if (push_back)
557                 _queue_node_push_back(&surface_queue->dirty_queue, node);
558         else
559                 _queue_node_push_front(&surface_queue->dirty_queue, node);
560 }
561
562 static queue_node *
563 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
564 {
565         queue_node *node;
566
567         if (_queue_is_empty(&surface_queue->free_queue)) {
568                 if (surface_queue->impl && surface_queue->impl->need_attach)
569                         surface_queue->impl->need_attach(surface_queue);
570
571                 if (_queue_is_empty(&surface_queue->free_queue)) {
572                         TBM_LOG_E("surface_queue->free_queue is empty.\n");
573                         return NULL;
574                 }
575         }
576
577         node = _queue_node_pop_front(&surface_queue->free_queue);
578
579         return node;
580 }
581
582 static queue_node *
583 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
584 {
585         queue_node *node;
586
587         if (_queue_is_empty(&surface_queue->dirty_queue))
588                 return NULL;
589
590         node = _queue_node_pop_front(&surface_queue->dirty_queue);
591
592         return node;
593 }
594
595 static void
596 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
597                            queue_node *node, int push_back)
598 {
599         if (push_back)
600                 _queue_node_push_back(&surface_queue->free_queue, node);
601         else
602                 _queue_node_push_front(&surface_queue->free_queue, node);
603 }
604
605 static void
606 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
607                         int queue_size,
608                         int width, int height, int format,
609                         const tbm_surface_queue_interface *impl, void *data)
610 {
611         TBM_RETURN_IF_FAIL(surface_queue != NULL);
612         TBM_RETURN_IF_FAIL(impl != NULL);
613
614         if (!g_surf_queue_bufmgr)
615                 _init_tbm_surf_queue_bufmgr();
616
617         pthread_mutex_init(&surface_queue->lock, NULL);
618         pthread_cond_init(&surface_queue->free_cond, NULL);
619         pthread_cond_init(&surface_queue->dirty_cond, NULL);
620
621         surface_queue->queue_size = queue_size;
622         surface_queue->width = width;
623         surface_queue->height = height;
624         surface_queue->format = format;
625         surface_queue->impl = impl;
626         surface_queue->impl_data = data;
627
628         _queue_init(&surface_queue->free_queue);
629         _queue_init(&surface_queue->dirty_queue);
630         LIST_INITHEAD(&surface_queue->list);
631
632         LIST_INITHEAD(&surface_queue->destory_noti);
633         LIST_INITHEAD(&surface_queue->dequeuable_noti);
634         LIST_INITHEAD(&surface_queue->dequeue_noti);
635         LIST_INITHEAD(&surface_queue->can_dequeue_noti);
636         LIST_INITHEAD(&surface_queue->acquirable_noti);
637         LIST_INITHEAD(&surface_queue->reset_noti);
638         LIST_INITHEAD(&surface_queue->trace_noti);
639
640         if (surface_queue->impl && surface_queue->impl->init)
641                 surface_queue->impl->init(surface_queue);
642
643         LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
644 }
645
646 tbm_surface_queue_error_e
647 tbm_surface_queue_add_destroy_cb(
648         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
649         void *data)
650 {
651         _tbm_surf_queue_mutex_lock();
652
653         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
654                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
655
656         pthread_mutex_lock(&surface_queue->lock);
657
658         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
659
660         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
661
662         pthread_mutex_unlock(&surface_queue->lock);
663
664         _tbm_surf_queue_mutex_unlock();
665
666         return TBM_SURFACE_QUEUE_ERROR_NONE;
667 }
668
669 tbm_surface_queue_error_e
670 tbm_surface_queue_remove_destroy_cb(
671         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
672         void *data)
673 {
674         _tbm_surf_queue_mutex_lock();
675
676         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
677                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
678
679         pthread_mutex_lock(&surface_queue->lock);
680
681         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
682
683         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
684
685         pthread_mutex_unlock(&surface_queue->lock);
686
687         _tbm_surf_queue_mutex_unlock();
688
689         return TBM_SURFACE_QUEUE_ERROR_NONE;
690 }
691
692 tbm_surface_queue_error_e
693 tbm_surface_queue_add_dequeuable_cb(
694         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
695         void *data)
696 {
697         _tbm_surf_queue_mutex_lock();
698
699         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
700                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
701
702         pthread_mutex_lock(&surface_queue->lock);
703
704         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
705
706         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
707
708         pthread_mutex_unlock(&surface_queue->lock);
709
710         _tbm_surf_queue_mutex_unlock();
711
712         return TBM_SURFACE_QUEUE_ERROR_NONE;
713 }
714
715 tbm_surface_queue_error_e
716 tbm_surface_queue_remove_dequeuable_cb(
717         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
718         void *data)
719 {
720         _tbm_surf_queue_mutex_lock();
721
722         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
723                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
724
725         pthread_mutex_lock(&surface_queue->lock);
726
727         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
728
729         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
730
731         pthread_mutex_unlock(&surface_queue->lock);
732
733         _tbm_surf_queue_mutex_unlock();
734
735         return TBM_SURFACE_QUEUE_ERROR_NONE;
736 }
737
738 tbm_surface_queue_error_e
739 tbm_surface_queue_add_dequeue_cb(
740         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
741         void *data)
742 {
743         _tbm_surf_queue_mutex_lock();
744
745         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
746                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
747
748         pthread_mutex_lock(&surface_queue->lock);
749
750         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
751
752         _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
753
754         pthread_mutex_unlock(&surface_queue->lock);
755
756         _tbm_surf_queue_mutex_unlock();
757
758         return TBM_SURFACE_QUEUE_ERROR_NONE;
759 }
760
761 tbm_surface_queue_error_e
762 tbm_surface_queue_remove_dequeue_cb(
763         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
764         void *data)
765 {
766         _tbm_surf_queue_mutex_lock();
767
768         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
769                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
770
771         pthread_mutex_lock(&surface_queue->lock);
772
773         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
774
775         _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
776
777         pthread_mutex_unlock(&surface_queue->lock);
778
779         _tbm_surf_queue_mutex_unlock();
780
781         return TBM_SURFACE_QUEUE_ERROR_NONE;
782 }
783
784 tbm_surface_queue_error_e
785 tbm_surface_queue_add_can_dequeue_cb(
786         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
787         void *data)
788 {
789         _tbm_surf_queue_mutex_lock();
790
791         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
792                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
793
794         pthread_mutex_lock(&surface_queue->lock);
795
796         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
797
798         _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
799
800         pthread_mutex_unlock(&surface_queue->lock);
801
802         _tbm_surf_queue_mutex_unlock();
803
804         return TBM_SURFACE_QUEUE_ERROR_NONE;
805 }
806
807 tbm_surface_queue_error_e
808 tbm_surface_queue_remove_can_dequeue_cb(
809         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
810         void *data)
811 {
812         _tbm_surf_queue_mutex_lock();
813
814         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
815                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
816
817         pthread_mutex_lock(&surface_queue->lock);
818
819         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
820
821         _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
822
823         pthread_mutex_unlock(&surface_queue->lock);
824
825         _tbm_surf_queue_mutex_unlock();
826
827         return TBM_SURFACE_QUEUE_ERROR_NONE;
828 }
829
830 tbm_surface_queue_error_e
831 tbm_surface_queue_add_acquirable_cb(
832         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
833         void *data)
834 {
835         _tbm_surf_queue_mutex_lock();
836
837         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
838                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
839
840         pthread_mutex_lock(&surface_queue->lock);
841
842         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
843
844         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
845
846         pthread_mutex_unlock(&surface_queue->lock);
847
848         _tbm_surf_queue_mutex_unlock();
849
850         return TBM_SURFACE_QUEUE_ERROR_NONE;
851 }
852
853 tbm_surface_queue_error_e
854 tbm_surface_queue_remove_acquirable_cb(
855         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
856         void *data)
857 {
858         _tbm_surf_queue_mutex_lock();
859
860         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
861                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
862
863         pthread_mutex_lock(&surface_queue->lock);
864
865         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
866
867         _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
868
869         pthread_mutex_unlock(&surface_queue->lock);
870
871         _tbm_surf_queue_mutex_unlock();
872
873         return TBM_SURFACE_QUEUE_ERROR_NONE;
874 }
875
876 tbm_surface_queue_error_e
877 tbm_surface_queue_add_trace_cb(
878         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
879         void *data)
880 {
881         _tbm_surf_queue_mutex_lock();
882
883         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
884                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
885
886         pthread_mutex_lock(&surface_queue->lock);
887
888         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
889
890         _trace_add(&surface_queue->trace_noti, trace_cb, data);
891
892         pthread_mutex_unlock(&surface_queue->lock);
893
894         _tbm_surf_queue_mutex_unlock();
895
896         return TBM_SURFACE_QUEUE_ERROR_NONE;
897 }
898
899 tbm_surface_queue_error_e
900 tbm_surface_queue_remove_trace_cb(
901         tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
902         void *data)
903 {
904         _tbm_surf_queue_mutex_lock();
905
906         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
907                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
908
909         pthread_mutex_lock(&surface_queue->lock);
910
911         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
912
913         _trace_remove(&surface_queue->trace_noti, trace_cb, data);
914
915         pthread_mutex_unlock(&surface_queue->lock);
916
917         _tbm_surf_queue_mutex_unlock();
918
919         return TBM_SURFACE_QUEUE_ERROR_NONE;
920 }
921
922 tbm_surface_queue_error_e
923 tbm_surface_queue_set_alloc_cb(
924         tbm_surface_queue_h surface_queue,
925         tbm_surface_alloc_cb alloc_cb,
926         tbm_surface_free_cb free_cb,
927         void *data)
928 {
929         _tbm_surf_queue_mutex_lock();
930
931         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
932                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
933
934         pthread_mutex_lock(&surface_queue->lock);
935
936         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
937
938         surface_queue->alloc_cb = alloc_cb;
939         surface_queue->free_cb = free_cb;
940         surface_queue->alloc_cb_data = data;
941
942         pthread_mutex_unlock(&surface_queue->lock);
943
944         _tbm_surf_queue_mutex_unlock();
945
946         return TBM_SURFACE_QUEUE_ERROR_NONE;
947 }
948
949 int
950 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
951 {
952         int width;
953
954         _tbm_surf_queue_mutex_lock();
955
956         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
957
958         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
959
960         width = surface_queue->width;
961
962         _tbm_surf_queue_mutex_unlock();
963
964         return width;
965 }
966
967 int
968 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
969 {
970         int height;
971
972         _tbm_surf_queue_mutex_lock();
973
974         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
975
976         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
977
978         height = surface_queue->height;
979
980         _tbm_surf_queue_mutex_unlock();
981
982         return height;
983 }
984
985 int
986 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
987 {
988         int format;
989
990         _tbm_surf_queue_mutex_lock();
991
992         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
993
994         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
995
996         format = surface_queue->format;
997
998         _tbm_surf_queue_mutex_unlock();
999
1000         return format;
1001 }
1002
1003 int
1004 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1005 {
1006         int queue_size;
1007
1008         _tbm_surf_queue_mutex_lock();
1009
1010         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1011
1012         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1013
1014         queue_size = surface_queue->queue_size;
1015
1016         _tbm_surf_queue_mutex_unlock();
1017
1018         return queue_size;
1019 }
1020
1021 tbm_surface_queue_error_e
1022 tbm_surface_queue_add_reset_cb(
1023         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1024         void *data)
1025 {
1026         _tbm_surf_queue_mutex_lock();
1027
1028         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1029                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1030
1031         pthread_mutex_lock(&surface_queue->lock);
1032
1033         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1034
1035         _notify_add(&surface_queue->reset_noti, reset_cb, data);
1036
1037         pthread_mutex_unlock(&surface_queue->lock);
1038
1039         _tbm_surf_queue_mutex_unlock();
1040
1041         return TBM_SURFACE_QUEUE_ERROR_NONE;
1042 }
1043
1044 tbm_surface_queue_error_e
1045 tbm_surface_queue_remove_reset_cb(
1046         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1047         void *data)
1048 {
1049         _tbm_surf_queue_mutex_lock();
1050
1051         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1052                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1053
1054         pthread_mutex_lock(&surface_queue->lock);
1055
1056         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1057
1058         _notify_remove(&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_enqueue(tbm_surface_queue_h
1069                           surface_queue, tbm_surface_h surface)
1070 {
1071         queue_node *node;
1072         int queue_type;
1073
1074         _tbm_surf_queue_mutex_lock();
1075
1076         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1077                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1078         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1079                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1080
1081         if (b_dump_queue)
1082                 tbm_surface_internal_dump_buffer(surface, "enqueue");
1083
1084         pthread_mutex_lock(&surface_queue->lock);
1085
1086         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1087
1088         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1089         if (node == NULL || queue_type != NODE_LIST) {
1090                 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1091                         node, queue_type);
1092                 pthread_mutex_unlock(&surface_queue->lock);
1093
1094                 _tbm_surf_queue_mutex_unlock();
1095                 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1096         }
1097
1098         if (surface_queue->impl && surface_queue->impl->enqueue)
1099                 surface_queue->impl->enqueue(surface_queue, node);
1100         else
1101                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1102
1103         if (_queue_is_empty(&surface_queue->dirty_queue)) {
1104                 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1105                 pthread_mutex_unlock(&surface_queue->lock);
1106
1107                 _tbm_surf_queue_mutex_unlock();
1108                 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1109         }
1110
1111         node->type = QUEUE_NODE_TYPE_ENQUEUE;
1112
1113         pthread_mutex_unlock(&surface_queue->lock);
1114         pthread_cond_signal(&surface_queue->dirty_cond);
1115
1116         _tbm_surf_queue_mutex_unlock();
1117
1118         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1119
1120         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1121
1122         return TBM_SURFACE_QUEUE_ERROR_NONE;
1123 }
1124
1125 tbm_surface_queue_error_e
1126 tbm_surface_queue_dequeue(tbm_surface_queue_h
1127                           surface_queue, tbm_surface_h *surface)
1128 {
1129         queue_node *node;
1130
1131         _tbm_surf_queue_mutex_lock();
1132
1133         *surface = NULL;
1134
1135         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1136                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1137         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1138                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1139
1140         pthread_mutex_lock(&surface_queue->lock);
1141
1142         if (surface_queue->impl && surface_queue->impl->dequeue)
1143                 node = surface_queue->impl->dequeue(surface_queue);
1144         else
1145                 node = _tbm_surface_queue_dequeue(surface_queue);
1146
1147         if (node == NULL || node->surface == NULL) {
1148                 TBM_LOG_E("_queue_node_pop_front failed\n");
1149                 pthread_mutex_unlock(&surface_queue->lock);
1150
1151                 _tbm_surf_queue_mutex_unlock();
1152                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1153         }
1154
1155         node->type = QUEUE_NODE_TYPE_DEQUEUE;
1156         *surface = node->surface;
1157
1158         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1159
1160         pthread_mutex_unlock(&surface_queue->lock);
1161
1162         _tbm_surf_queue_mutex_unlock();
1163
1164         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1165
1166         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1167
1168         return TBM_SURFACE_QUEUE_ERROR_NONE;
1169 }
1170
1171 int
1172 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1173 {
1174         _tbm_surf_queue_mutex_lock();
1175
1176         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1177
1178         _tbm_surf_queue_mutex_unlock();
1179
1180         _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1181
1182         _tbm_surf_queue_mutex_lock();
1183
1184         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1185
1186         pthread_mutex_lock(&surface_queue->lock);
1187
1188         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1189
1190         if (_queue_is_empty(&surface_queue->free_queue)) {
1191                 if (surface_queue->impl && surface_queue->impl->need_attach)
1192                         surface_queue->impl->need_attach(surface_queue);
1193
1194                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1195                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1196                         _tbm_surf_queue_mutex_unlock();
1197                         return 0;
1198                 }
1199         }
1200
1201         if (!_queue_is_empty(&surface_queue->free_queue)) {
1202                 pthread_mutex_unlock(&surface_queue->lock);
1203                 _tbm_surf_queue_mutex_unlock();
1204                 return 1;
1205         }
1206
1207         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1208                                                 QUEUE_NODE_TYPE_ACQUIRE)) {
1209                 _tbm_surf_queue_mutex_unlock();
1210                 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1211                 _tbm_surf_queue_mutex_lock();
1212
1213                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1214                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1215                         pthread_mutex_unlock(&surface_queue->lock);
1216                         _tbm_surf_queue_mutex_unlock();
1217                         return 0;
1218                 }
1219
1220                 pthread_mutex_unlock(&surface_queue->lock);
1221                 _tbm_surf_queue_mutex_unlock();
1222                 return 1;
1223         }
1224
1225         pthread_mutex_unlock(&surface_queue->lock);
1226         _tbm_surf_queue_mutex_unlock();
1227         return 0;
1228 }
1229
1230 tbm_surface_queue_error_e
1231 tbm_surface_queue_release(tbm_surface_queue_h
1232                           surface_queue, tbm_surface_h surface)
1233 {
1234         queue_node *node;
1235         int queue_type;
1236
1237         _tbm_surf_queue_mutex_lock();
1238
1239         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1240                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1241         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1242                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1243
1244         pthread_mutex_lock(&surface_queue->lock);
1245
1246         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1247
1248         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1249         if (node == NULL || queue_type != NODE_LIST) {
1250                 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1251                         node, queue_type);
1252                 pthread_mutex_unlock(&surface_queue->lock);
1253
1254                 _tbm_surf_queue_mutex_unlock();
1255                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1256         }
1257
1258         if (surface_queue->queue_size < surface_queue->num_attached) {
1259                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1260
1261                 if (surface_queue->impl && surface_queue->impl->need_detach)
1262                         surface_queue->impl->need_detach(surface_queue, node);
1263                 else
1264                         _tbm_surface_queue_detach(surface_queue, surface);
1265
1266                 pthread_mutex_unlock(&surface_queue->lock);
1267
1268                 _tbm_surf_queue_mutex_unlock();
1269                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1270         }
1271
1272         if (surface_queue->impl && surface_queue->impl->release)
1273                 surface_queue->impl->release(surface_queue, node);
1274         else
1275                 _tbm_surface_queue_release(surface_queue, node, 1);
1276
1277         if (_queue_is_empty(&surface_queue->free_queue)) {
1278                 pthread_mutex_unlock(&surface_queue->lock);
1279
1280                 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1281                 _tbm_surf_queue_mutex_unlock();
1282                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1283         }
1284
1285         node->type = QUEUE_NODE_TYPE_RELEASE;
1286
1287         pthread_mutex_unlock(&surface_queue->lock);
1288         pthread_cond_signal(&surface_queue->free_cond);
1289
1290         _tbm_surf_queue_mutex_unlock();
1291
1292         _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1293
1294         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1295
1296         return TBM_SURFACE_QUEUE_ERROR_NONE;
1297 }
1298
1299 tbm_surface_queue_error_e
1300 tbm_surface_queue_acquire(tbm_surface_queue_h
1301                           surface_queue, tbm_surface_h *surface)
1302 {
1303         queue_node *node;
1304
1305         _tbm_surf_queue_mutex_lock();
1306
1307         *surface = NULL;
1308
1309         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1310                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1311         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1312                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1313
1314         pthread_mutex_lock(&surface_queue->lock);
1315
1316         if (surface_queue->impl && surface_queue->impl->acquire)
1317                 node = surface_queue->impl->acquire(surface_queue);
1318         else
1319                 node = _tbm_surface_queue_acquire(surface_queue);
1320
1321         if (node == NULL || node->surface == NULL) {
1322                 TBM_LOG_E("_queue_node_pop_front failed\n");
1323                 pthread_mutex_unlock(&surface_queue->lock);
1324
1325                 _tbm_surf_queue_mutex_unlock();
1326                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1327         }
1328
1329         node->type = QUEUE_NODE_TYPE_ACQUIRE;
1330
1331         *surface = node->surface;
1332
1333         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1334
1335         pthread_mutex_unlock(&surface_queue->lock);
1336
1337         _tbm_surf_queue_mutex_unlock();
1338
1339         if (b_dump_queue)
1340                 tbm_surface_internal_dump_buffer(*surface, "acquire");
1341
1342         _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1343
1344         return TBM_SURFACE_QUEUE_ERROR_NONE;
1345 }
1346
1347 int
1348 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1349 {
1350         _tbm_surf_queue_mutex_lock();
1351
1352         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1353
1354         pthread_mutex_lock(&surface_queue->lock);
1355
1356         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1357
1358         if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1359                 pthread_mutex_unlock(&surface_queue->lock);
1360                 _tbm_surf_queue_mutex_unlock();
1361                 return 1;
1362         }
1363
1364         if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1365                                                 QUEUE_NODE_TYPE_DEQUEUE)) {
1366                 _tbm_surf_queue_mutex_unlock();
1367                 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1368                 _tbm_surf_queue_mutex_lock();
1369
1370                 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1371                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1372                         pthread_mutex_unlock(&surface_queue->lock);
1373                         _tbm_surf_queue_mutex_unlock();
1374                         return 0;
1375                 }
1376
1377                 pthread_mutex_unlock(&surface_queue->lock);
1378                 _tbm_surf_queue_mutex_unlock();
1379                 return 1;
1380         }
1381
1382         pthread_mutex_unlock(&surface_queue->lock);
1383         _tbm_surf_queue_mutex_unlock();
1384         return 0;
1385 }
1386
1387 void
1388 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1389 {
1390         queue_node *node = NULL, *tmp;
1391
1392         _tbm_surf_queue_mutex_lock();
1393
1394         TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1395
1396         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1397
1398         LIST_DEL(&surface_queue->item_link);
1399
1400         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1401                 _queue_delete_node(surface_queue, node);
1402
1403         if (surface_queue->impl && surface_queue->impl->destroy)
1404                 surface_queue->impl->destroy(surface_queue);
1405
1406         _notify_emit(surface_queue, &surface_queue->destory_noti);
1407
1408         _notify_remove_all(&surface_queue->destory_noti);
1409         _notify_remove_all(&surface_queue->dequeuable_noti);
1410         _notify_remove_all(&surface_queue->dequeue_noti);
1411         _notify_remove_all(&surface_queue->can_dequeue_noti);
1412         _notify_remove_all(&surface_queue->acquirable_noti);
1413         _notify_remove_all(&surface_queue->reset_noti);
1414         _trace_remove_all(&surface_queue->trace_noti);
1415
1416         pthread_mutex_destroy(&surface_queue->lock);
1417
1418         free(surface_queue);
1419
1420         if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1421                 _deinit_tbm_surf_queue_bufmgr();
1422
1423         _tbm_surf_queue_mutex_unlock();
1424 }
1425
1426 tbm_surface_queue_error_e
1427 tbm_surface_queue_reset(tbm_surface_queue_h
1428                         surface_queue, int width, int height, int format)
1429 {
1430         queue_node *node = NULL, *tmp;
1431
1432         _tbm_surf_queue_mutex_lock();
1433
1434         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1435                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1436
1437         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1438
1439         if (width == surface_queue->width && height == surface_queue->height &&
1440                 format == surface_queue->format) {
1441                 _tbm_surf_queue_mutex_unlock();
1442                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1443         }
1444
1445         pthread_mutex_lock(&surface_queue->lock);
1446
1447         surface_queue->width = width;
1448         surface_queue->height = height;
1449         surface_queue->format = format;
1450
1451         /* Destory surface and Push to free_queue */
1452         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1453                 _queue_delete_node(surface_queue, node);
1454
1455         /* Reset queue */
1456         _queue_init(&surface_queue->free_queue);
1457         _queue_init(&surface_queue->dirty_queue);
1458         LIST_INITHEAD(&surface_queue->list);
1459
1460         surface_queue->num_attached = 0;
1461
1462         if (surface_queue->impl && surface_queue->impl->reset)
1463                 surface_queue->impl->reset(surface_queue);
1464
1465         pthread_mutex_unlock(&surface_queue->lock);
1466         pthread_cond_signal(&surface_queue->free_cond);
1467
1468         _tbm_surf_queue_mutex_unlock();
1469
1470         _notify_emit(surface_queue, &surface_queue->reset_noti);
1471
1472         return TBM_SURFACE_QUEUE_ERROR_NONE;
1473 }
1474
1475 tbm_surface_queue_error_e
1476 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1477 {
1478         _tbm_surf_queue_mutex_lock();
1479
1480         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1481                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1482
1483         _tbm_surf_queue_mutex_unlock();
1484
1485         _notify_emit(surface_queue, &surface_queue->reset_noti);
1486
1487         return TBM_SURFACE_QUEUE_ERROR_NONE;
1488 }
1489
1490 tbm_surface_queue_error_e
1491 tbm_surface_queue_set_size(tbm_surface_queue_h
1492                         surface_queue, int queue_size, int flush)
1493 {
1494         queue_node *node = NULL, *tmp;
1495
1496         _tbm_surf_queue_mutex_lock();
1497
1498         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1499                                         TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1500         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1501                                         TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1502
1503         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1504
1505         if ((surface_queue->queue_size == queue_size) && !flush) {
1506                 _tbm_surf_queue_mutex_unlock();
1507                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1508         }
1509
1510         pthread_mutex_lock(&surface_queue->lock);
1511
1512         if (flush) {
1513                 /* Destory surface and Push to free_queue */
1514                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1515                         _queue_delete_node(surface_queue, node);
1516
1517                 /* Reset queue */
1518                 _queue_init(&surface_queue->free_queue);
1519                 _queue_init(&surface_queue->dirty_queue);
1520                 LIST_INITHEAD(&surface_queue->list);
1521
1522                 surface_queue->num_attached = 0;
1523                 surface_queue->queue_size = queue_size;
1524
1525                 if (surface_queue->impl && surface_queue->impl->reset)
1526                         surface_queue->impl->reset(surface_queue);
1527
1528                 pthread_mutex_unlock(&surface_queue->lock);
1529                 pthread_cond_signal(&surface_queue->free_cond);
1530
1531                 _tbm_surf_queue_mutex_unlock();
1532
1533                 _notify_emit(surface_queue, &surface_queue->reset_noti);
1534
1535                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1536         } else {
1537                 if (surface_queue->queue_size > queue_size) {
1538                         int need_del = surface_queue->queue_size - queue_size;
1539
1540                         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1541                                 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1542
1543                                 if (surface_queue->impl && surface_queue->impl->need_detach)
1544                                         surface_queue->impl->need_detach(surface_queue, node);
1545                                 else
1546                                         _tbm_surface_queue_detach(surface_queue, node->surface);
1547
1548                                 need_del--;
1549                                 if (need_del == 0)
1550                                         break;
1551                         }
1552                 }
1553
1554                 surface_queue->queue_size = queue_size;
1555
1556                 pthread_mutex_unlock(&surface_queue->lock);
1557
1558                 _tbm_surf_queue_mutex_unlock();
1559
1560                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1561         }
1562 }
1563
1564 tbm_surface_queue_error_e
1565 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1566 {
1567         queue_node *node = NULL, *tmp;
1568
1569         _tbm_surf_queue_mutex_lock();
1570
1571         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1572                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1573
1574         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1575
1576         if (surface_queue->num_attached == 0) {
1577                 _tbm_surf_queue_mutex_unlock();
1578                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1579         }
1580
1581         pthread_mutex_lock(&surface_queue->lock);
1582
1583         /* Destory surface and Push to free_queue */
1584         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1585                 _queue_delete_node(surface_queue, node);
1586
1587         /* Reset queue */
1588         _queue_init(&surface_queue->free_queue);
1589         _queue_init(&surface_queue->dirty_queue);
1590         LIST_INITHEAD(&surface_queue->list);
1591
1592         surface_queue->num_attached = 0;
1593
1594         if (surface_queue->impl && surface_queue->impl->reset)
1595                 surface_queue->impl->reset(surface_queue);
1596
1597         pthread_mutex_unlock(&surface_queue->lock);
1598         pthread_cond_signal(&surface_queue->free_cond);
1599
1600         _tbm_surf_queue_mutex_unlock();
1601
1602         _notify_emit(surface_queue, &surface_queue->reset_noti);
1603
1604         return TBM_SURFACE_QUEUE_ERROR_NONE;
1605 }
1606
1607 tbm_surface_queue_error_e
1608 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1609                         tbm_surface_h *surfaces, int *num)
1610 {
1611         queue_node *node = NULL;
1612
1613         _tbm_surf_queue_mutex_lock();
1614
1615         *num = 0;
1616
1617         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1618                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1619         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1620                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1621
1622         pthread_mutex_lock(&surface_queue->lock);
1623
1624         LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1625                 if (surfaces)
1626                         surfaces[*num] = node->surface;
1627
1628                 *num = *num + 1;
1629         }
1630
1631         pthread_mutex_unlock(&surface_queue->lock);
1632
1633         _tbm_surf_queue_mutex_unlock();
1634
1635         return TBM_SURFACE_QUEUE_ERROR_NONE;
1636 }
1637
1638 typedef struct {
1639         int flags;
1640 } tbm_queue_default;
1641
1642 static void
1643 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1644 {
1645         free(surface_queue->impl_data);
1646 }
1647
1648 static void
1649 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1650 {
1651         tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1652         tbm_surface_h surface;
1653
1654         if (surface_queue->queue_size == surface_queue->num_attached)
1655                 return;
1656
1657         if (surface_queue->alloc_cb) {
1658                 pthread_mutex_unlock(&surface_queue->lock);
1659                 _tbm_surf_queue_mutex_unlock();
1660                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1661                 _tbm_surf_queue_mutex_lock();
1662                 pthread_mutex_lock(&surface_queue->lock);
1663
1664                 /* silent return */
1665                 if (!surface)
1666                         return;
1667
1668                 tbm_surface_internal_ref(surface);
1669         } else {
1670                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1671                                 surface_queue->height,
1672                                 surface_queue->format,
1673                                 data->flags);
1674                 TBM_RETURN_IF_FAIL(surface != NULL);
1675         }
1676
1677         _tbm_surface_queue_attach(surface_queue, surface);
1678         tbm_surface_internal_unref(surface);
1679 }
1680
1681 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1682         NULL,                           /*__tbm_queue_default_init*/
1683         NULL,                           /*__tbm_queue_default_reset*/
1684         __tbm_queue_default_destroy,
1685         __tbm_queue_default_need_attach,
1686         NULL,                           /*__tbm_queue_default_enqueue*/
1687         NULL,                           /*__tbm_queue_default_release*/
1688         NULL,                           /*__tbm_queue_default_dequeue*/
1689         NULL,                           /*__tbm_queue_default_acquire*/
1690         NULL,                           /*__tbm_queue_default_need_detach*/
1691 };
1692
1693 tbm_surface_queue_h
1694 tbm_surface_queue_create(int queue_size, int width,
1695                          int height, int format, int flags)
1696 {
1697         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1698         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1699         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1700         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1701
1702         _tbm_surf_queue_mutex_lock();
1703
1704         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1705                                             sizeof(struct _tbm_surface_queue));
1706         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1707
1708         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1709
1710         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1711                                   sizeof(tbm_queue_default));
1712         if (data == NULL) {
1713                 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1714                 free(surface_queue);
1715                 _tbm_surf_queue_mutex_unlock();
1716                 return NULL;
1717         }
1718
1719         data->flags = flags;
1720         _tbm_surface_queue_init(surface_queue,
1721                                 queue_size,
1722                                 width, height, format,
1723                                 &tbm_queue_default_impl, data);
1724
1725         _tbm_surf_queue_mutex_unlock();
1726
1727         return surface_queue;
1728 }
1729
1730 typedef struct {
1731         int flags;
1732         queue dequeue_list;
1733 } tbm_queue_sequence;
1734
1735 static void
1736 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1737 {
1738         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1739
1740         _queue_init(&data->dequeue_list);
1741 }
1742
1743 static void
1744 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1745 {
1746         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1747
1748         _queue_init(&data->dequeue_list);
1749 }
1750
1751 static void
1752 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1753 {
1754         free(surface_queue->impl_data);
1755 }
1756
1757 static void
1758 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1759 {
1760         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1761         tbm_surface_h surface;
1762
1763         if (surface_queue->queue_size == surface_queue->num_attached)
1764                 return;
1765
1766         if (surface_queue->alloc_cb) {
1767                 pthread_mutex_unlock(&surface_queue->lock);
1768                 _tbm_surf_queue_mutex_unlock();
1769                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1770                 _tbm_surf_queue_mutex_lock();
1771                 pthread_mutex_lock(&surface_queue->lock);
1772
1773                 /* silent return */
1774                 if (!surface)
1775                         return;
1776
1777                 tbm_surface_internal_ref(surface);
1778         } else {
1779                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1780                                 surface_queue->height,
1781                                 surface_queue->format,
1782                                 data->flags);
1783                 TBM_RETURN_IF_FAIL(surface != NULL);
1784         }
1785
1786         _tbm_surface_queue_attach(surface_queue, surface);
1787         tbm_surface_internal_unref(surface);
1788 }
1789
1790 static void
1791 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1792                              queue_node *node)
1793 {
1794         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1795         queue_node *next = NULL, *tmp;
1796
1797         node->priv_flags = 0;
1798
1799         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1800                 if (next->priv_flags)
1801                         break;
1802                 _queue_node_pop(&data->dequeue_list, next);
1803                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1804         }
1805 }
1806
1807 static queue_node *
1808 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1809                              surface_queue)
1810 {
1811         tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1812         queue_node *node;
1813
1814         node = _tbm_surface_queue_dequeue(surface_queue);
1815         if (node) {
1816                 _queue_node_push_back(&data->dequeue_list, node);
1817                 node->priv_flags = 1;
1818         }
1819
1820         return node;
1821 }
1822
1823 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1824         __tbm_queue_sequence_init,
1825         __tbm_queue_sequence_reset,
1826         __tbm_queue_sequence_destroy,
1827         __tbm_queue_sequence_need_attach,
1828         __tbm_queue_sequence_enqueue,
1829         NULL,                                   /*__tbm_queue_sequence_release*/
1830         __tbm_queue_sequence_dequeue,
1831         NULL,                                   /*__tbm_queue_sequence_acquire*/
1832         NULL,                                   /*__tbm_queue_sequence_need_dettach*/
1833 };
1834
1835 tbm_surface_queue_h
1836 tbm_surface_queue_sequence_create(int queue_size, int width,
1837                                   int height, int format, int flags)
1838 {
1839         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1840         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1841         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1842         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1843
1844         _tbm_surf_queue_mutex_lock();
1845
1846         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1847                                             sizeof(struct _tbm_surface_queue));
1848         TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1849
1850         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1851
1852         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1853                                    sizeof(tbm_queue_sequence));
1854         if (data == NULL) {
1855                 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
1856                 free(surface_queue);
1857                 _tbm_surf_queue_mutex_unlock();
1858                 return NULL;
1859         }
1860
1861         data->flags = flags;
1862         _tbm_surface_queue_init(surface_queue,
1863                                 queue_size,
1864                                 width, height, format,
1865                                 &tbm_queue_sequence_impl, data);
1866
1867         _tbm_surf_queue_mutex_unlock();
1868
1869         return surface_queue;
1870 }
1871 /* LCOV_EXCL_STOP */