queue: move queue_size to common
[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 "tbm_bufmgr_int.h"
33 #include "list.h"
34
35 #define FREE_QUEUE      1
36 #define DIRTY_QUEUE     2
37 #define NODE_LIST       4
38
39 #define DEBUG 0
40
41 #if DEBUG
42 #define TBM_TRACE() TBM_LOG("[TRACE] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
45 #else
46 #define TBM_TRACE()
47 #define TBM_LOCK()
48 #define TBM_UNLOCK()
49 #endif
50
51 typedef struct {
52         struct list_head head;
53         struct list_head tail;
54
55         int count;
56 } queue;
57
58 typedef struct {
59         tbm_surface_h surface;
60
61         struct list_head item_link;
62         struct list_head link;
63
64         unsigned int priv_flags;        /*for each queue*/
65 } queue_node;
66
67 typedef struct {
68         struct list_head link;
69
70         tbm_surface_queue_notify_cb cb;
71         void *data;
72 } queue_notify;
73
74 typedef struct _tbm_surface_queue_interface {
75         void (*init)(tbm_surface_queue_h queue);
76         void (*reset)(tbm_surface_queue_h queue);
77         void (*destroy)(tbm_surface_queue_h queue);
78         void (*need_attach)(tbm_surface_queue_h queue);
79
80         void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
81         void (*release)(tbm_surface_queue_h queue, queue_node *node);
82         queue_node *(*dequeue)(tbm_surface_queue_h queue);
83         queue_node *(*acquire)(tbm_surface_queue_h queue);
84 } tbm_surface_queue_interface;
85
86 struct _tbm_surface_queue {
87         int width;
88         int height;
89         int format;
90         int queue_size;
91
92         queue free_queue;
93         queue dirty_queue;
94         struct list_head list;
95
96         struct list_head destory_noti;
97         struct list_head dequeuable_noti;
98         struct list_head acquirable_noti;
99         struct list_head reset_noti;
100
101         tbm_surface_queue_notify_cb destroy_cb;
102         void *destroy_cb_data;
103
104         tbm_surface_queue_notify_cb dequeuable_cb;
105         void *dequeuable_cb_data;
106
107         tbm_surface_queue_notify_cb acquirable_cb;
108         void *acquirable_cb_data;
109
110         tbm_surface_queue_notify_cb reset_cb;
111         void *reset_cb_data;
112
113         pthread_mutex_t lock;
114         pthread_cond_t free_cond;
115         pthread_cond_t dirty_cond;
116
117         const tbm_surface_queue_interface *impl;
118         void *impl_data;
119
120         //For external buffer allocation
121         tbm_surface_alloc_cb alloc_cb;
122         tbm_surface_free_cb free_cb;
123         void *alloc_cb_data;
124 };
125
126 static queue_node *
127 _queue_node_create(void)
128 {
129         queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
130
131         TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
132
133         return node;
134 }
135
136 static void
137 _queue_node_delete(queue_node *node)
138 {
139         LIST_DEL(&node->item_link);
140         LIST_DEL(&node->link);
141         free(node);
142 }
143
144 static int
145 _queue_is_empty(queue *queue)
146 {
147         if (queue->head.next == &queue->tail)
148                 return 1;
149
150         return 0;
151 }
152
153 static void
154 _queue_node_push_back(queue *queue, queue_node *node)
155 {
156         LIST_ADDTAIL(&node->item_link, &queue->tail);
157         queue->count++;
158 }
159
160 static void
161 _queue_node_push_front(queue *queue, queue_node *node)
162 {
163         LIST_ADD(&node->item_link, &queue->head);
164         queue->count++;
165 }
166
167 static queue_node *
168 _queue_node_pop_front(queue *queue)
169 {
170         queue_node *node = NULL;
171
172         node = LIST_ENTRY(queue_node, queue->head.next, item_link);
173
174         LIST_DEL(&node->item_link);
175         queue->count--;
176
177         return node;
178 }
179
180 static queue_node *
181 _queue_node_pop(queue *queue, queue_node *node)
182 {
183         LIST_DEL(&node->item_link);
184         queue->count--;
185
186         return node;
187 }
188
189 static queue_node *
190 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
191                 tbm_surface_h surface, int *out_type)
192 {
193         queue_node *node = NULL;
194         queue_node *tmp = NULL;
195
196         if (type == 0)
197                 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
198         if (out_type)
199                 *out_type = 0;
200
201         if (type & FREE_QUEUE) {
202                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
203                                          item_link) {
204                         if (node->surface == surface) {
205                                 if (out_type)
206                                         *out_type = FREE_QUEUE;
207
208                                 return node;
209                         }
210                 }
211         }
212
213         if (type & DIRTY_QUEUE) {
214                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
215                                          item_link) {
216                         if (node->surface == surface) {
217                                 if (out_type)
218                                         *out_type = DIRTY_QUEUE;
219
220                                 return node;
221                         }
222                 }
223         }
224
225         if (type & NODE_LIST) {
226                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
227                         if (node->surface == surface) {
228                                 if (out_type)
229                                         *out_type = NODE_LIST;
230
231                                 return node;
232                         }
233                 }
234         }
235
236         return NULL;
237 }
238
239 static void
240 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
241 {
242         if (node->surface) {
243                 if (surface_queue->free_cb) {
244                         surface_queue->free_cb(surface_queue,
245                                         surface_queue->alloc_cb_data,
246                                         node->surface);
247                 } else {
248                         tbm_surface_destroy(node->surface);
249                 }
250         }
251
252         _queue_node_delete(node);
253 }
254
255 static void
256 _queue_init(queue *queue)
257 {
258         LIST_INITHEAD(&queue->head);
259         LIST_INITHEAD(&queue->tail);
260         LIST_ADDTAIL(&queue->head, &queue->tail);
261         queue->count = 0;
262 }
263
264 static void
265 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
266             void *data)
267 {
268         TBM_RETURN_IF_FAIL(cb != NULL);
269
270         queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
271
272         TBM_RETURN_IF_FAIL(item != NULL);
273
274         LIST_INITHEAD(&item->link);
275         item->cb = cb;
276         item->data = data;
277
278         LIST_ADDTAIL(&item->link, list);
279 }
280
281 static void
282 _notify_remove(struct list_head *list,
283                tbm_surface_queue_notify_cb cb, void *data)
284 {
285         queue_notify *item = NULL, *tmp = NULL;
286
287         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
288                 if (item->cb == cb && item->data == data) {
289                         LIST_DEL(&item->link);
290                         free(item);
291                         return;
292                 }
293         }
294
295         TBM_LOG("Cannot find notifiy\n");
296 }
297
298 static void
299 _notify_remove_all(struct list_head *list)
300 {
301         queue_notify *item = NULL, *tmp = NULL;
302
303         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
304                 LIST_DEL(&item->link);
305                 free(item);
306         }
307 }
308
309 static void
310 _notify_emit(tbm_surface_queue_h surface_queue,
311              struct list_head *list)
312 {
313         queue_notify *item = NULL, *tmp = NULL;
314
315         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
316                 item->cb(surface_queue, item->data);
317         }
318 }
319
320 void
321 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
322                           tbm_surface_h surface)
323 {
324         queue_node *node = NULL;
325
326         node = _queue_node_create();
327         TBM_RETURN_IF_FAIL(node != NULL);
328
329         tbm_surface_internal_ref(surface);
330         node->surface = surface;
331
332         LIST_ADDTAIL(&node->link, &surface_queue->list);
333         _queue_node_push_back(&surface_queue->free_queue, node);
334 }
335
336 void
337 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
338                           tbm_surface_h surface)
339 {
340         queue_node *node = NULL;
341         int queue_type;
342
343         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
344         if (node)
345                 _queue_delete_node(surface_queue, node);
346 }
347
348 void
349 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
350                            queue_node *node, int push_back)
351 {
352         if (push_back)
353                 _queue_node_push_back(&surface_queue->dirty_queue, node);
354         else
355                 _queue_node_push_front(&surface_queue->dirty_queue, node);
356 }
357
358 queue_node *
359 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
360 {
361         queue_node *node = NULL;
362
363         if (_queue_is_empty(&surface_queue->free_queue)) {
364                 if (surface_queue->impl && surface_queue->impl->need_attach)
365                         surface_queue->impl->need_attach(surface_queue);
366
367                 if (_queue_is_empty(&surface_queue->free_queue))
368                         return NULL;
369         }
370
371         node = _queue_node_pop_front(&surface_queue->free_queue);
372
373         return node;
374 }
375
376 queue_node *
377 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
378 {
379         queue_node *node = NULL;
380
381         if (_queue_is_empty(&surface_queue->dirty_queue))
382                 return NULL;
383
384         node = _queue_node_pop_front(&surface_queue->dirty_queue);
385
386         return node;
387 }
388
389 void
390 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
391                            queue_node *node, int push_back)
392 {
393         if (push_back)
394                 _queue_node_push_back(&surface_queue->free_queue, node);
395         else
396                 _queue_node_push_front(&surface_queue->free_queue, node);
397 }
398
399 void
400 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
401                         int queue_size,
402                         int width, int height, int format,
403                         const tbm_surface_queue_interface *impl, void *data)
404 {
405         TBM_RETURN_IF_FAIL(surface_queue != NULL);
406         TBM_RETURN_IF_FAIL(impl != NULL);
407
408         memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
409
410         pthread_mutex_init(&surface_queue->lock, NULL);
411         pthread_cond_init(&surface_queue->free_cond, NULL);
412         pthread_cond_init(&surface_queue->dirty_cond, NULL);
413
414         surface_queue->queue_size = queue_size;
415         surface_queue->width = width;
416         surface_queue->height = height;
417         surface_queue->format = format;
418         surface_queue->impl = impl;
419         surface_queue->impl_data = data;
420
421         _queue_init(&surface_queue->free_queue);
422         _queue_init(&surface_queue->dirty_queue);
423         LIST_INITHEAD(&surface_queue->list);
424
425         LIST_INITHEAD(&surface_queue->destory_noti);
426         LIST_INITHEAD(&surface_queue->acquirable_noti);
427         LIST_INITHEAD(&surface_queue->dequeuable_noti);
428         LIST_INITHEAD(&surface_queue->reset_noti);
429
430         if (surface_queue->impl && surface_queue->impl->init)
431                 surface_queue->impl->init(surface_queue);
432 }
433
434 tbm_surface_queue_error_e
435 tbm_surface_queue_set_destroy_cb(
436         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
437         void *data)
438 {
439         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
440                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
441
442         pthread_mutex_lock(&surface_queue->lock);
443
444         surface_queue->destroy_cb = destroy_cb;
445         surface_queue->destroy_cb_data = data;
446
447         pthread_mutex_unlock(&surface_queue->lock);
448
449         return TBM_SURFACE_QUEUE_ERROR_NONE;
450 }
451
452 tbm_surface_queue_error_e
453 tbm_surface_queue_add_destroy_cb(
454         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
455         void *data)
456 {
457         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
458                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
459
460         pthread_mutex_lock(&surface_queue->lock);
461
462         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
463
464         pthread_mutex_unlock(&surface_queue->lock);
465
466         return TBM_SURFACE_QUEUE_ERROR_NONE;
467 }
468
469 tbm_surface_queue_error_e
470 tbm_surface_queue_remove_destroy_cb(
471         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
472         void *data)
473 {
474         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
475                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
476
477         pthread_mutex_lock(&surface_queue->lock);
478
479         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
480
481         pthread_mutex_unlock(&surface_queue->lock);
482
483         return TBM_SURFACE_QUEUE_ERROR_NONE;
484 }
485
486 tbm_surface_queue_error_e
487 tbm_surface_queue_set_dequeuable_cb(
488         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
489         void *data)
490 {
491         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
492                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
493
494         pthread_mutex_lock(&surface_queue->lock);
495
496         surface_queue->dequeuable_cb = dequeuable_cb;
497         surface_queue->dequeuable_cb_data = data;
498
499         pthread_mutex_unlock(&surface_queue->lock);
500
501         return TBM_SURFACE_QUEUE_ERROR_NONE;
502 }
503
504 tbm_surface_queue_error_e
505 tbm_surface_queue_add_dequeuable_cb(
506         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
507         void *data)
508 {
509         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
510                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
511
512         pthread_mutex_lock(&surface_queue->lock);
513
514         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
515
516         pthread_mutex_unlock(&surface_queue->lock);
517
518         return TBM_SURFACE_QUEUE_ERROR_NONE;
519 }
520
521 tbm_surface_queue_error_e
522 tbm_surface_queue_remove_dequeuable_cb(
523         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
524         void *data)
525 {
526         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
527                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
528
529         pthread_mutex_lock(&surface_queue->lock);
530
531         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
532
533         pthread_mutex_unlock(&surface_queue->lock);
534
535         return TBM_SURFACE_QUEUE_ERROR_NONE;
536 }
537
538 tbm_surface_queue_error_e
539 tbm_surface_queue_set_acquirable_cb(
540         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
541         void *data)
542 {
543         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
544                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
545
546         pthread_mutex_lock(&surface_queue->lock);
547
548         surface_queue->acquirable_cb = acquirable_cb;
549         surface_queue->acquirable_cb_data = data;
550
551         pthread_mutex_unlock(&surface_queue->lock);
552
553         return TBM_SURFACE_QUEUE_ERROR_NONE;
554 }
555
556 tbm_surface_queue_error_e
557 tbm_surface_queue_add_acquirable_cb(
558         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
559         void *data)
560 {
561         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
562                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
563
564         pthread_mutex_lock(&surface_queue->lock);
565
566         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
567
568         pthread_mutex_unlock(&surface_queue->lock);
569
570         return TBM_SURFACE_QUEUE_ERROR_NONE;
571 }
572
573 tbm_surface_queue_error_e
574 tbm_surface_queue_remove_acquirable_cb(
575         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
576         void *data)
577 {
578         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
579                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
580
581         pthread_mutex_lock(&surface_queue->lock);
582
583         _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
584
585         pthread_mutex_unlock(&surface_queue->lock);
586
587         return TBM_SURFACE_QUEUE_ERROR_NONE;
588 }
589
590 tbm_surface_queue_error_e
591 tbm_surface_queue_set_alloc_cb(
592         tbm_surface_queue_h surface_queue,
593         tbm_surface_alloc_cb alloc_cb,
594         tbm_surface_free_cb free_cb,
595         void *data)
596 {
597         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
598                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
599
600         pthread_mutex_lock(&surface_queue->lock);
601
602         surface_queue->alloc_cb = alloc_cb;
603         surface_queue->free_cb = free_cb;
604         surface_queue->alloc_cb_data = data;
605
606         pthread_mutex_unlock(&surface_queue->lock);
607
608         return TBM_SURFACE_QUEUE_ERROR_NONE;
609 }
610
611 int
612 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
613 {
614         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
615
616         return surface_queue->width;
617 }
618
619 int
620 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
621 {
622         return surface_queue->height;
623 }
624
625 int
626 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
627 {
628         return surface_queue->format;
629 }
630
631 int
632 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
633 {
634         return surface_queue->queue_size;
635 }
636
637 tbm_surface_queue_error_e
638 tbm_surface_queue_set_reset_cb(
639         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
640         void *data)
641 {
642         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
643                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
644
645         pthread_mutex_lock(&surface_queue->lock);
646
647         surface_queue->reset_cb = reset_cb;
648         surface_queue->reset_cb_data = data;
649
650         pthread_mutex_unlock(&surface_queue->lock);
651
652         return TBM_SURFACE_QUEUE_ERROR_NONE;
653 }
654
655 tbm_surface_queue_error_e
656 tbm_surface_queue_add_reset_cb(
657         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
658         void *data)
659 {
660         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
661                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
662
663         pthread_mutex_lock(&surface_queue->lock);
664
665         _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
666
667         pthread_mutex_unlock(&surface_queue->lock);
668
669         return TBM_SURFACE_QUEUE_ERROR_NONE;
670 }
671
672 tbm_surface_queue_error_e
673 tbm_surface_queue_remove_reset_cb(
674         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
675         void *data)
676 {
677         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
678                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
679
680         pthread_mutex_lock(&surface_queue->lock);
681
682         _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
683
684         pthread_mutex_unlock(&surface_queue->lock);
685
686         return TBM_SURFACE_QUEUE_ERROR_NONE;
687 }
688
689 tbm_surface_queue_error_e
690 tbm_surface_queue_enqueue(tbm_surface_queue_h
691                           surface_queue, tbm_surface_h surface)
692 {
693         queue_node *node = NULL;
694         int queue_type;
695
696         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
697                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
698         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
699                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
700
701         pthread_mutex_lock(&surface_queue->lock);
702
703         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
704         if (node == NULL || queue_type != NODE_LIST) {
705                 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
706                         node, queue_type);
707                 pthread_mutex_unlock(&surface_queue->lock);
708                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
709         }
710
711         if (surface_queue->impl && surface_queue->impl->enqueue)
712                 surface_queue->impl->enqueue(surface_queue, node);
713         else
714                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
715
716         if (_queue_is_empty(&surface_queue->dirty_queue)) {
717                 pthread_mutex_unlock(&surface_queue->lock);
718                 return TBM_SURFACE_QUEUE_ERROR_NONE;
719         }
720
721         pthread_mutex_unlock(&surface_queue->lock);
722         pthread_cond_signal(&surface_queue->dirty_cond);
723
724         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
725         if (surface_queue->acquirable_cb)
726                 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
727
728         return TBM_SURFACE_QUEUE_ERROR_NONE;
729 }
730
731 tbm_surface_queue_error_e
732 tbm_surface_queue_dequeue(tbm_surface_queue_h
733                           surface_queue, tbm_surface_h *surface)
734 {
735         queue_node *node = NULL;
736
737         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
738                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
739         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
740                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
741
742         pthread_mutex_lock(&surface_queue->lock);
743
744         if (surface_queue->impl && surface_queue->impl->dequeue)
745                 node = surface_queue->impl->dequeue(surface_queue);
746         else
747                 node = _tbm_surface_queue_dequeue(surface_queue);
748
749         if (node == NULL) {
750                 *surface = NULL;
751                 pthread_mutex_unlock(&surface_queue->lock);
752                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
753         }
754
755         if (node->surface == NULL) {
756                 *surface = NULL;
757                 TBM_LOG("_queue_node_pop_front  failed\n");
758                 pthread_mutex_unlock(&surface_queue->lock);
759                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
760         }
761
762         *surface = node->surface;
763
764         pthread_mutex_unlock(&surface_queue->lock);
765
766         return TBM_SURFACE_QUEUE_ERROR_NONE;
767 }
768
769 int
770 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
771 {
772         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
773
774         pthread_mutex_lock(&surface_queue->lock);
775
776         if (_queue_is_empty(&surface_queue->free_queue)) {
777                 if (surface_queue->impl && surface_queue->impl->need_attach)
778                         surface_queue->impl->need_attach(surface_queue);
779         }
780
781         if (_queue_is_empty(&surface_queue->free_queue)) {
782                 if (wait) {
783                         pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
784                         pthread_mutex_unlock(&surface_queue->lock);
785                         return 1;
786                 }
787
788                 pthread_mutex_unlock(&surface_queue->lock);
789                 return 0;
790         }
791
792         pthread_mutex_unlock(&surface_queue->lock);
793
794         return 1;
795 }
796
797 tbm_surface_queue_error_e
798 tbm_surface_queue_release(tbm_surface_queue_h
799                           surface_queue, tbm_surface_h surface)
800 {
801         queue_node *node = NULL;
802         int queue_type;
803
804         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
805                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
806         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
807                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
808
809         pthread_mutex_lock(&surface_queue->lock);
810
811         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
812         if (node == NULL || queue_type != NODE_LIST) {
813                 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
814                         node, queue_type);
815                 pthread_mutex_unlock(&surface_queue->lock);
816                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
817         }
818
819         if (surface_queue->impl && surface_queue->impl->release)
820                 surface_queue->impl->release(surface_queue, node);
821         else
822                 _tbm_surface_queue_release(surface_queue, node, 1);
823
824         if (_queue_is_empty(&surface_queue->free_queue)) {
825                 pthread_mutex_unlock(&surface_queue->lock);
826                 return TBM_SURFACE_QUEUE_ERROR_NONE;
827         }
828
829         pthread_mutex_unlock(&surface_queue->lock);
830         pthread_cond_signal(&surface_queue->free_cond);
831
832         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
833         if (surface_queue->dequeuable_cb)
834                 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
835
836         return TBM_SURFACE_QUEUE_ERROR_NONE;
837 }
838
839 tbm_surface_queue_error_e
840 tbm_surface_queue_acquire(tbm_surface_queue_h
841                           surface_queue, tbm_surface_h *surface)
842 {
843         queue_node *node = NULL;
844
845         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
846                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
847         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
848                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
849
850         pthread_mutex_lock(&surface_queue->lock);
851
852         if (surface_queue->impl && surface_queue->impl->acquire)
853                 node = surface_queue->impl->acquire(surface_queue);
854         else
855                 node = _tbm_surface_queue_acquire(surface_queue);
856
857         if (node == NULL) {
858                 *surface = NULL;
859                 pthread_mutex_unlock(&surface_queue->lock);
860                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
861         }
862
863         if (node->surface == NULL) {
864                 *surface = NULL;
865                 TBM_LOG("_queue_node_pop_front  failed\n");
866                 pthread_mutex_unlock(&surface_queue->lock);
867                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
868         }
869
870         *surface = node->surface;
871
872         pthread_mutex_unlock(&surface_queue->lock);
873
874         return TBM_SURFACE_QUEUE_ERROR_NONE;
875 }
876
877 int
878 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
879 {
880         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
881
882         pthread_mutex_lock(&surface_queue->lock);
883
884         if (_queue_is_empty(&surface_queue->dirty_queue)) {
885                 if (wait) {
886                         pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
887                         pthread_mutex_unlock(&surface_queue->lock);
888                         return 1;
889                 }
890
891                 pthread_mutex_unlock(&surface_queue->lock);
892                 return 0;
893         }
894
895         pthread_mutex_unlock(&surface_queue->lock);
896
897         return 1;
898 }
899
900 void
901 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
902 {
903         queue_node *node = NULL, *tmp = NULL;
904
905         TBM_RETURN_IF_FAIL(surface_queue != NULL);
906
907         if (surface_queue->destroy_cb)
908                 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
909
910         _notify_emit(surface_queue, &surface_queue->destory_noti);
911
912         if (surface_queue->impl && surface_queue->impl->destroy)
913                 surface_queue->impl->destroy(surface_queue);
914
915         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
916                 _queue_delete_node(surface_queue, node);
917         }
918
919         _notify_remove_all(&surface_queue->destory_noti);
920         _notify_remove_all(&surface_queue->acquirable_noti);
921         _notify_remove_all(&surface_queue->dequeuable_noti);
922         _notify_remove_all(&surface_queue->reset_noti);
923
924         pthread_mutex_destroy(&surface_queue->lock);
925         free(surface_queue);
926 }
927
928 tbm_surface_queue_error_e
929 tbm_surface_queue_reset(tbm_surface_queue_h
930                         surface_queue, int width, int height, int format)
931 {
932         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
933                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
934
935         queue_node *node = NULL, *tmp = NULL;
936
937         if (width == surface_queue->width && height == surface_queue->height &&
938             format == surface_queue->format)
939                 return TBM_SURFACE_QUEUE_ERROR_NONE;
940
941         pthread_mutex_lock(&surface_queue->lock);
942
943         surface_queue->width = width;
944         surface_queue->height = height;
945         surface_queue->format = format;
946
947         /* Destory surface and Push to free_queue */
948         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
949                 _queue_delete_node(surface_queue, node);
950         }
951
952         /* Reset queue */
953         _queue_init(&surface_queue->free_queue);
954         _queue_init(&surface_queue->dirty_queue);
955         LIST_INITHEAD(&surface_queue->list);
956
957         if (surface_queue->impl && surface_queue->impl->reset)
958                 surface_queue->impl->reset(surface_queue);
959
960         pthread_mutex_unlock(&surface_queue->lock);
961         pthread_cond_signal(&surface_queue->free_cond);
962
963         _notify_emit(surface_queue, &surface_queue->reset_noti);
964         if (surface_queue->reset_cb)
965                 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
966
967         return TBM_SURFACE_QUEUE_ERROR_NONE;
968 }
969
970 tbm_surface_queue_error_e
971 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
972 {
973         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
974                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
975
976         queue_node *node = NULL, *tmp = NULL;
977
978         pthread_mutex_lock(&surface_queue->lock);
979
980         /* Destory surface and Push to free_queue */
981         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
982                 _queue_delete_node(surface_queue, node);
983         }
984
985         /* Reset queue */
986         _queue_init(&surface_queue->free_queue);
987         _queue_init(&surface_queue->dirty_queue);
988         LIST_INITHEAD(&surface_queue->list);
989
990         if (surface_queue->impl && surface_queue->impl->reset)
991                 surface_queue->impl->reset(surface_queue);
992
993         _notify_emit(surface_queue, &surface_queue->reset_noti);
994         if (surface_queue->reset_cb)
995                 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
996
997         pthread_mutex_unlock(&surface_queue->lock);
998         pthread_cond_signal(&surface_queue->free_cond);
999
1000         return TBM_SURFACE_QUEUE_ERROR_NONE;
1001 }
1002
1003 typedef struct {
1004         int queue_size;
1005         int num_attached;
1006         int flags;
1007 } tbm_queue_default;
1008
1009 static void
1010 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1011 {
1012         tbm_queue_default *data = surface_queue->impl_data;
1013
1014         data->num_attached = 0;
1015 }
1016
1017 static void
1018 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1019 {
1020         tbm_queue_default *data = surface_queue->impl_data;
1021
1022         data->num_attached = 0;
1023 }
1024
1025 static void
1026 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1027 {
1028         free(surface_queue->impl_data);
1029 }
1030
1031 static void
1032 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1033 {
1034         tbm_queue_default *data = surface_queue->impl_data;
1035         tbm_surface_h surface;
1036
1037         if (data->queue_size == data->num_attached)
1038                 return;
1039
1040         if (surface_queue->alloc_cb) {
1041                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1042                 TBM_RETURN_IF_FAIL(surface != NULL);
1043                 tbm_surface_internal_ref(surface);
1044         } else {
1045                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1046                                 surface_queue->height,
1047                                 surface_queue->format,
1048                                 data->flags);
1049                 TBM_RETURN_IF_FAIL(surface != NULL);
1050         }
1051
1052         _tbm_surface_queue_attach(surface_queue, surface);
1053         tbm_surface_internal_unref(surface);
1054         data->num_attached++;
1055 }
1056
1057 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1058         __tbm_queue_default_init,
1059         __tbm_queue_default_reset,
1060         __tbm_queue_default_destroy,
1061         __tbm_queue_default_need_attach,
1062         NULL,                           /*__tbm_queue_default_enqueue*/
1063         NULL,                           /*__tbm_queue_default_release*/
1064         NULL,                           /*__tbm_queue_default_dequeue*/
1065         NULL,                           /*__tbm_queue_default_acquire*/
1066 };
1067
1068 tbm_surface_queue_h
1069 tbm_surface_queue_create(int queue_size, int width,
1070                          int height, int format, int flags)
1071 {
1072         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1073         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1074         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1075         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1076
1077         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1078                                             sizeof(struct _tbm_surface_queue));
1079         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1080
1081         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1082                                   sizeof(tbm_queue_default));
1083         if (data == NULL) {
1084                 free(surface_queue);
1085                 return NULL;
1086         }
1087
1088         data->queue_size = queue_size;
1089         data->flags = flags;
1090         _tbm_surface_queue_init(surface_queue,
1091                                 data->queue_size,
1092                                 width, height, format,
1093                                 &tbm_queue_default_impl, data);
1094
1095         return surface_queue;
1096 }
1097
1098 typedef struct {
1099         int queue_size;
1100         int num_attached;
1101         int flags;
1102         queue dequeue_list;
1103 } tbm_queue_sequence;
1104
1105 static void
1106 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1107 {
1108         tbm_queue_sequence *data = surface_queue->impl_data;
1109
1110         data->num_attached = 0;
1111         _queue_init(&data->dequeue_list);
1112 }
1113
1114 static void
1115 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1116 {
1117         tbm_queue_sequence *data = surface_queue->impl_data;
1118
1119         data->num_attached = 0;
1120         _queue_init(&data->dequeue_list);
1121 }
1122
1123 static void
1124 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1125 {
1126         free(surface_queue->impl_data);
1127 }
1128
1129 static void
1130 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1131 {
1132         tbm_queue_sequence *data = surface_queue->impl_data;
1133         tbm_surface_h surface;
1134
1135         if (data->queue_size == data->num_attached)
1136                 return;
1137
1138         if (surface_queue->alloc_cb) {
1139                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1140                 TBM_RETURN_IF_FAIL(surface != NULL);
1141                 tbm_surface_internal_ref(surface);
1142         } else {
1143                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1144                                 surface_queue->height,
1145                                 surface_queue->format,
1146                                 data->flags);
1147                 TBM_RETURN_IF_FAIL(surface != NULL);
1148         }
1149
1150         _tbm_surface_queue_attach(surface_queue, surface);
1151         tbm_surface_internal_unref(surface);
1152         data->num_attached++;
1153 }
1154
1155 static void
1156 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1157                              queue_node *node)
1158 {
1159         tbm_queue_sequence *data = surface_queue->impl_data;
1160         queue_node *next = NULL;
1161         queue_node *tmp = NULL;
1162
1163         node->priv_flags = 0;
1164
1165         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1166                 if (next->priv_flags)
1167                         break;
1168                 _queue_node_pop(&data->dequeue_list, next);
1169                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1170         }
1171 }
1172
1173 static queue_node *
1174 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1175                              surface_queue)
1176 {
1177         tbm_queue_sequence *data = surface_queue->impl_data;
1178         queue_node *node = NULL;
1179
1180         node = _tbm_surface_queue_dequeue(surface_queue);
1181         if (node) {
1182                 _queue_node_push_back(&data->dequeue_list, node);
1183                 node->priv_flags = 1;
1184         }
1185
1186         return node;
1187 }
1188
1189 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1190         __tbm_queue_sequence_init,
1191         __tbm_queue_sequence_reset,
1192         __tbm_queue_sequence_destroy,
1193         __tbm_queue_sequence_need_attach,
1194         __tbm_queue_sequence_enqueue,
1195         NULL,                                   /*__tbm_queue_sequence_release*/
1196         __tbm_queue_sequence_dequeue,
1197         NULL,                                   /*__tbm_queue_sequence_acquire*/
1198 };
1199
1200 tbm_surface_queue_h
1201 tbm_surface_queue_sequence_create(int queue_size, int width,
1202                                   int height, int format, int flags)
1203 {
1204         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1205         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1206         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1207         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1208
1209         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1210                                             sizeof(struct _tbm_surface_queue));
1211         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1212
1213         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1214                                    sizeof(tbm_queue_sequence));
1215         if (data == NULL) {
1216                 free(surface_queue);
1217                 return NULL;
1218         }
1219
1220         data->queue_size = queue_size;
1221         data->flags = flags;
1222         _tbm_surface_queue_init(surface_queue,
1223                                 data->queue_size,
1224                                 width, height, format,
1225                                 &tbm_queue_sequence_impl, data);
1226
1227         return surface_queue;
1228 }