1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
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.
30 **************************************************************************/
34 #include "tbm_bufmgr_int.h"
41 #define TBM_QUEUE_DEBUG 0
44 #define TBM_QUEUE_TRACE(fmt, ...) { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
46 #define TBM_QUEUE_TRACE(fmt, ...)
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)
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);
62 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
64 TBM_LOG_E("'%s' failed.\n", #cond);\
65 _tbm_surf_queue_mutex_unlock();\
70 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
72 TBM_LOG_E("'%s' failed.\n", #cond);\
73 _tbm_surf_queue_mutex_unlock();\
78 typedef enum _queue_node_type {
80 QUEUE_NODE_TYPE_DEQUEUE,
81 QUEUE_NODE_TYPE_ENQUEUE,
82 QUEUE_NODE_TYPE_ACQUIRE,
83 QUEUE_NODE_TYPE_RELEASE
87 struct list_head head;
92 tbm_surface_h surface;
94 struct list_head item_link;
95 struct list_head link;
99 unsigned int priv_flags; /*for each queue*/
103 struct list_head link;
105 tbm_surface_queue_notify_cb cb;
110 struct list_head link;
112 tbm_surface_queue_trace_cb cb;
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);
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;
129 struct _tbm_surface_queue {
138 struct list_head list;
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;
148 pthread_mutex_t lock;
149 pthread_cond_t free_cond;
150 pthread_cond_t dirty_cond;
152 const tbm_surface_queue_interface *impl;
155 //For external buffer allocation
156 tbm_surface_alloc_cb alloc_cb;
157 tbm_surface_free_cb free_cb;
160 struct list_head item_link; /* link of surface queue */
163 /* LCOV_EXCL_START */
166 _tbm_surf_queue_mutex_init(void)
168 static bool tbm_surf_queue_mutex_init = false;
170 if (tbm_surf_queue_mutex_init)
173 if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
174 TBM_LOG_E("fail: pthread_mutex_init\n");
178 tbm_surf_queue_mutex_init = true;
184 _tbm_surf_queue_mutex_lock(void)
186 if (!_tbm_surf_queue_mutex_init()) {
187 TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n");
191 pthread_mutex_lock(&tbm_surf_queue_lock);
195 _tbm_surf_queue_mutex_unlock(void)
197 pthread_mutex_unlock(&tbm_surf_queue_lock);
201 _init_tbm_surf_queue_bufmgr(void)
203 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
207 _deinit_tbm_surf_queue_bufmgr(void)
209 if (!g_surf_queue_bufmgr)
212 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
213 g_surf_queue_bufmgr = NULL;
217 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
219 tbm_surface_queue_h old_data = NULL;
221 if (surface_queue == NULL) {
222 TBM_LOG_E("error: surface_queue is NULL.\n");
226 if (g_surf_queue_bufmgr == NULL) {
227 TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n");
231 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
232 TBM_LOG_E("error: surf_queue_list is empty\n");
236 LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
238 if (old_data == surface_queue) {
239 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
244 TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
250 _queue_node_create(void)
252 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
254 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
260 _queue_node_delete(queue_node *node)
262 LIST_DEL(&node->item_link);
263 LIST_DEL(&node->link);
268 _queue_is_empty(queue *queue)
270 if (LIST_IS_EMPTY(&queue->head))
277 _queue_node_push_back(queue *queue, queue_node *node)
279 LIST_ADDTAIL(&node->item_link, &queue->head);
284 _queue_node_push_front(queue *queue, queue_node *node)
286 LIST_ADD(&node->item_link, &queue->head);
291 _queue_node_pop_front(queue *queue)
295 if (!queue->head.next) return NULL;
296 if (!queue->count) return NULL;
298 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
300 LIST_DELINIT(&node->item_link);
307 _queue_node_pop(queue *queue, queue_node *node)
309 LIST_DELINIT(&node->item_link);
316 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
317 tbm_surface_h surface, int *out_type)
319 queue_node *node = NULL;
322 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
326 if (type & FREE_QUEUE) {
327 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
329 if (node->surface == surface) {
331 *out_type = FREE_QUEUE;
338 if (type & DIRTY_QUEUE) {
339 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
341 if (node->surface == surface) {
343 *out_type = DIRTY_QUEUE;
350 if (type & NODE_LIST) {
351 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
352 if (node->surface == surface) {
354 *out_type = NODE_LIST;
361 TBM_LOG_E("fail to get the queue_node.\n");
367 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
370 if (surface_queue->free_cb) {
371 surface_queue->free_cb(surface_queue,
372 surface_queue->alloc_cb_data,
376 tbm_surface_destroy(node->surface);
379 _queue_node_delete(node);
383 _queue_init(queue *queue)
385 LIST_INITHEAD(&queue->head);
391 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
394 TBM_RETURN_IF_FAIL(cb != NULL);
396 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
398 TBM_RETURN_IF_FAIL(item != NULL);
400 LIST_INITHEAD(&item->link);
404 LIST_ADDTAIL(&item->link, list);
408 _notify_remove(struct list_head *list,
409 tbm_surface_queue_notify_cb cb, void *data)
411 queue_notify *item = NULL, *tmp;
413 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
414 if (item->cb == cb && item->data == data) {
415 LIST_DEL(&item->link);
421 TBM_LOG_E("Cannot find notifiy\n");
425 _notify_remove_all(struct list_head *list)
427 queue_notify *item = NULL, *tmp;
429 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
430 LIST_DEL(&item->link);
436 _notify_emit(tbm_surface_queue_h surface_queue,
437 struct list_head *list)
439 queue_notify *item = NULL, *tmp;;
442 The item->cb is the outside function of the libtbm.
443 The tbm user may/can remove the item of the list,
444 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
446 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
447 item->cb(surface_queue, item->data);
451 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
454 TBM_RETURN_IF_FAIL(cb != NULL);
456 queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
458 TBM_RETURN_IF_FAIL(item != NULL);
460 LIST_INITHEAD(&item->link);
464 LIST_ADDTAIL(&item->link, list);
468 _trace_remove(struct list_head *list,
469 tbm_surface_queue_trace_cb cb, void *data)
471 queue_trace *item = NULL, *tmp;
473 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
474 if (item->cb == cb && item->data == data) {
475 LIST_DEL(&item->link);
481 TBM_LOG_E("Cannot find notifiy\n");
485 _trace_remove_all(struct list_head *list)
487 queue_trace *item = NULL, *tmp;
489 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
490 LIST_DEL(&item->link);
496 _trace_emit(tbm_surface_queue_h surface_queue,
497 struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
499 queue_trace *item = NULL, *tmp;;
502 The item->cb is the outside function of the libtbm.
503 The tbm user may/can remove the item of the list,
504 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
506 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
507 item->cb(surface_queue, surface, trace, item->data);
511 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
513 queue_node *node = NULL;
516 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
517 if (node->type == type)
525 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
526 tbm_surface_h surface)
530 node = _queue_node_create();
531 TBM_RETURN_IF_FAIL(node != NULL);
533 tbm_surface_internal_ref(surface);
534 node->surface = surface;
536 LIST_ADDTAIL(&node->link, &surface_queue->list);
537 surface_queue->num_attached++;
538 _queue_node_push_back(&surface_queue->free_queue, node);
542 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
543 tbm_surface_h surface)
548 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
550 _queue_delete_node(surface_queue, node);
551 surface_queue->num_attached--;
556 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
557 queue_node *node, int push_back)
560 _queue_node_push_back(&surface_queue->dirty_queue, node);
562 _queue_node_push_front(&surface_queue->dirty_queue, node);
566 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
570 if (_queue_is_empty(&surface_queue->free_queue)) {
571 if (surface_queue->impl && surface_queue->impl->need_attach)
572 surface_queue->impl->need_attach(surface_queue);
574 if (_queue_is_empty(&surface_queue->free_queue)) {
575 TBM_LOG_E("surface_queue->free_queue is empty.\n");
580 node = _queue_node_pop_front(&surface_queue->free_queue);
586 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
590 if (_queue_is_empty(&surface_queue->dirty_queue))
593 node = _queue_node_pop_front(&surface_queue->dirty_queue);
599 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
600 queue_node *node, int push_back)
603 _queue_node_push_back(&surface_queue->free_queue, node);
605 _queue_node_push_front(&surface_queue->free_queue, node);
609 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
611 int width, int height, int format,
612 const tbm_surface_queue_interface *impl, void *data)
614 TBM_RETURN_IF_FAIL(surface_queue != NULL);
615 TBM_RETURN_IF_FAIL(impl != NULL);
617 if (!g_surf_queue_bufmgr)
618 _init_tbm_surf_queue_bufmgr();
620 pthread_mutex_init(&surface_queue->lock, NULL);
621 pthread_cond_init(&surface_queue->free_cond, NULL);
622 pthread_cond_init(&surface_queue->dirty_cond, NULL);
624 surface_queue->queue_size = queue_size;
625 surface_queue->width = width;
626 surface_queue->height = height;
627 surface_queue->format = format;
628 surface_queue->impl = impl;
629 surface_queue->impl_data = data;
631 _queue_init(&surface_queue->free_queue);
632 _queue_init(&surface_queue->dirty_queue);
633 LIST_INITHEAD(&surface_queue->list);
635 LIST_INITHEAD(&surface_queue->destory_noti);
636 LIST_INITHEAD(&surface_queue->dequeuable_noti);
637 LIST_INITHEAD(&surface_queue->dequeue_noti);
638 LIST_INITHEAD(&surface_queue->can_dequeue_noti);
639 LIST_INITHEAD(&surface_queue->acquirable_noti);
640 LIST_INITHEAD(&surface_queue->reset_noti);
641 LIST_INITHEAD(&surface_queue->trace_noti);
643 if (surface_queue->impl && surface_queue->impl->init)
644 surface_queue->impl->init(surface_queue);
646 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
649 tbm_surface_queue_error_e
650 tbm_surface_queue_add_destroy_cb(
651 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
654 _tbm_surf_queue_mutex_lock();
656 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
657 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
659 pthread_mutex_lock(&surface_queue->lock);
661 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
663 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
665 pthread_mutex_unlock(&surface_queue->lock);
667 _tbm_surf_queue_mutex_unlock();
669 return TBM_SURFACE_QUEUE_ERROR_NONE;
672 tbm_surface_queue_error_e
673 tbm_surface_queue_remove_destroy_cb(
674 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
677 _tbm_surf_queue_mutex_lock();
679 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
680 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
682 pthread_mutex_lock(&surface_queue->lock);
684 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
686 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
688 pthread_mutex_unlock(&surface_queue->lock);
690 _tbm_surf_queue_mutex_unlock();
692 return TBM_SURFACE_QUEUE_ERROR_NONE;
695 tbm_surface_queue_error_e
696 tbm_surface_queue_add_dequeuable_cb(
697 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
700 _tbm_surf_queue_mutex_lock();
702 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
703 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
705 pthread_mutex_lock(&surface_queue->lock);
707 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
709 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
711 pthread_mutex_unlock(&surface_queue->lock);
713 _tbm_surf_queue_mutex_unlock();
715 return TBM_SURFACE_QUEUE_ERROR_NONE;
718 tbm_surface_queue_error_e
719 tbm_surface_queue_remove_dequeuable_cb(
720 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
723 _tbm_surf_queue_mutex_lock();
725 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
726 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
728 pthread_mutex_lock(&surface_queue->lock);
730 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
732 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
734 pthread_mutex_unlock(&surface_queue->lock);
736 _tbm_surf_queue_mutex_unlock();
738 return TBM_SURFACE_QUEUE_ERROR_NONE;
741 tbm_surface_queue_error_e
742 tbm_surface_queue_add_dequeue_cb(
743 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
746 _tbm_surf_queue_mutex_lock();
748 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
749 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
751 pthread_mutex_lock(&surface_queue->lock);
753 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
755 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
757 pthread_mutex_unlock(&surface_queue->lock);
759 _tbm_surf_queue_mutex_unlock();
761 return TBM_SURFACE_QUEUE_ERROR_NONE;
764 tbm_surface_queue_error_e
765 tbm_surface_queue_remove_dequeue_cb(
766 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
769 _tbm_surf_queue_mutex_lock();
771 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
772 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
774 pthread_mutex_lock(&surface_queue->lock);
776 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
778 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
780 pthread_mutex_unlock(&surface_queue->lock);
782 _tbm_surf_queue_mutex_unlock();
784 return TBM_SURFACE_QUEUE_ERROR_NONE;
787 tbm_surface_queue_error_e
788 tbm_surface_queue_add_can_dequeue_cb(
789 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
792 _tbm_surf_queue_mutex_lock();
794 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
795 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
797 pthread_mutex_lock(&surface_queue->lock);
799 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
801 _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
803 pthread_mutex_unlock(&surface_queue->lock);
805 _tbm_surf_queue_mutex_unlock();
807 return TBM_SURFACE_QUEUE_ERROR_NONE;
810 tbm_surface_queue_error_e
811 tbm_surface_queue_remove_can_dequeue_cb(
812 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
815 _tbm_surf_queue_mutex_lock();
817 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
818 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
820 pthread_mutex_lock(&surface_queue->lock);
822 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
824 _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
826 pthread_mutex_unlock(&surface_queue->lock);
828 _tbm_surf_queue_mutex_unlock();
830 return TBM_SURFACE_QUEUE_ERROR_NONE;
833 tbm_surface_queue_error_e
834 tbm_surface_queue_add_acquirable_cb(
835 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
838 _tbm_surf_queue_mutex_lock();
840 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
841 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
843 pthread_mutex_lock(&surface_queue->lock);
845 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
847 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
849 pthread_mutex_unlock(&surface_queue->lock);
851 _tbm_surf_queue_mutex_unlock();
853 return TBM_SURFACE_QUEUE_ERROR_NONE;
856 tbm_surface_queue_error_e
857 tbm_surface_queue_remove_acquirable_cb(
858 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
861 _tbm_surf_queue_mutex_lock();
863 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
864 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
866 pthread_mutex_lock(&surface_queue->lock);
868 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
870 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
872 pthread_mutex_unlock(&surface_queue->lock);
874 _tbm_surf_queue_mutex_unlock();
876 return TBM_SURFACE_QUEUE_ERROR_NONE;
879 tbm_surface_queue_error_e
880 tbm_surface_queue_add_trace_cb(
881 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
884 _tbm_surf_queue_mutex_lock();
886 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
887 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
889 pthread_mutex_lock(&surface_queue->lock);
891 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
893 _trace_add(&surface_queue->trace_noti, trace_cb, data);
895 pthread_mutex_unlock(&surface_queue->lock);
897 _tbm_surf_queue_mutex_unlock();
899 return TBM_SURFACE_QUEUE_ERROR_NONE;
902 tbm_surface_queue_error_e
903 tbm_surface_queue_remove_trace_cb(
904 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
907 _tbm_surf_queue_mutex_lock();
909 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
910 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
912 pthread_mutex_lock(&surface_queue->lock);
914 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
916 _trace_remove(&surface_queue->trace_noti, trace_cb, data);
918 pthread_mutex_unlock(&surface_queue->lock);
920 _tbm_surf_queue_mutex_unlock();
922 return TBM_SURFACE_QUEUE_ERROR_NONE;
925 tbm_surface_queue_error_e
926 tbm_surface_queue_set_alloc_cb(
927 tbm_surface_queue_h surface_queue,
928 tbm_surface_alloc_cb alloc_cb,
929 tbm_surface_free_cb free_cb,
932 _tbm_surf_queue_mutex_lock();
934 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
935 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
937 pthread_mutex_lock(&surface_queue->lock);
939 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
941 surface_queue->alloc_cb = alloc_cb;
942 surface_queue->free_cb = free_cb;
943 surface_queue->alloc_cb_data = data;
945 pthread_mutex_unlock(&surface_queue->lock);
947 _tbm_surf_queue_mutex_unlock();
949 return TBM_SURFACE_QUEUE_ERROR_NONE;
953 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
957 _tbm_surf_queue_mutex_lock();
959 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
961 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
963 width = surface_queue->width;
965 _tbm_surf_queue_mutex_unlock();
971 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
975 _tbm_surf_queue_mutex_lock();
977 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
979 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
981 height = surface_queue->height;
983 _tbm_surf_queue_mutex_unlock();
989 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
993 _tbm_surf_queue_mutex_lock();
995 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
997 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
999 format = surface_queue->format;
1001 _tbm_surf_queue_mutex_unlock();
1007 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1011 _tbm_surf_queue_mutex_lock();
1013 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1015 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1017 queue_size = surface_queue->queue_size;
1019 _tbm_surf_queue_mutex_unlock();
1024 tbm_surface_queue_error_e
1025 tbm_surface_queue_add_reset_cb(
1026 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1029 _tbm_surf_queue_mutex_lock();
1031 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1032 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1034 pthread_mutex_lock(&surface_queue->lock);
1036 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1038 _notify_add(&surface_queue->reset_noti, reset_cb, data);
1040 pthread_mutex_unlock(&surface_queue->lock);
1042 _tbm_surf_queue_mutex_unlock();
1044 return TBM_SURFACE_QUEUE_ERROR_NONE;
1047 tbm_surface_queue_error_e
1048 tbm_surface_queue_remove_reset_cb(
1049 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1052 _tbm_surf_queue_mutex_lock();
1054 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1055 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1057 pthread_mutex_lock(&surface_queue->lock);
1059 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1061 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1063 pthread_mutex_unlock(&surface_queue->lock);
1065 _tbm_surf_queue_mutex_unlock();
1067 return TBM_SURFACE_QUEUE_ERROR_NONE;
1070 tbm_surface_queue_error_e
1071 tbm_surface_queue_enqueue(tbm_surface_queue_h
1072 surface_queue, tbm_surface_h surface)
1077 _tbm_surf_queue_mutex_lock();
1079 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1080 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1081 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1082 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1085 tbm_surface_internal_dump_buffer(surface, "enqueue");
1087 pthread_mutex_lock(&surface_queue->lock);
1089 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1091 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1092 if (node == NULL || queue_type != NODE_LIST) {
1093 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1095 pthread_mutex_unlock(&surface_queue->lock);
1097 _tbm_surf_queue_mutex_unlock();
1100 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1102 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1105 if (surface_queue->impl && surface_queue->impl->enqueue)
1106 surface_queue->impl->enqueue(surface_queue, node);
1108 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1110 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1111 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1112 pthread_mutex_unlock(&surface_queue->lock);
1114 _tbm_surf_queue_mutex_unlock();
1115 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1118 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1120 pthread_mutex_unlock(&surface_queue->lock);
1121 pthread_cond_signal(&surface_queue->dirty_cond);
1123 _tbm_surf_queue_mutex_unlock();
1125 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1127 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1129 return TBM_SURFACE_QUEUE_ERROR_NONE;
1132 tbm_surface_queue_error_e
1133 tbm_surface_queue_dequeue(tbm_surface_queue_h
1134 surface_queue, tbm_surface_h *surface)
1138 _tbm_surf_queue_mutex_lock();
1142 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1143 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1144 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1145 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1147 pthread_mutex_lock(&surface_queue->lock);
1149 if (surface_queue->impl && surface_queue->impl->dequeue)
1150 node = surface_queue->impl->dequeue(surface_queue);
1152 node = _tbm_surface_queue_dequeue(surface_queue);
1154 if (node == NULL || node->surface == NULL) {
1155 TBM_LOG_E("_queue_node_pop_front failed\n");
1156 pthread_mutex_unlock(&surface_queue->lock);
1158 _tbm_surf_queue_mutex_unlock();
1159 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1162 node->type = QUEUE_NODE_TYPE_DEQUEUE;
1163 *surface = node->surface;
1165 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1167 pthread_mutex_unlock(&surface_queue->lock);
1169 _tbm_surf_queue_mutex_unlock();
1171 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1173 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1175 return TBM_SURFACE_QUEUE_ERROR_NONE;
1179 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1181 _tbm_surf_queue_mutex_lock();
1183 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1185 _tbm_surf_queue_mutex_unlock();
1187 _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1189 _tbm_surf_queue_mutex_lock();
1191 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1193 pthread_mutex_lock(&surface_queue->lock);
1195 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1197 if (_queue_is_empty(&surface_queue->free_queue)) {
1198 if (surface_queue->impl && surface_queue->impl->need_attach)
1199 surface_queue->impl->need_attach(surface_queue);
1201 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1202 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1203 pthread_mutex_unlock(&surface_queue->lock);
1204 _tbm_surf_queue_mutex_unlock();
1209 if (!_queue_is_empty(&surface_queue->free_queue)) {
1210 pthread_mutex_unlock(&surface_queue->lock);
1211 _tbm_surf_queue_mutex_unlock();
1215 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1216 QUEUE_NODE_TYPE_ACQUIRE)) {
1217 _tbm_surf_queue_mutex_unlock();
1218 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1219 _tbm_surf_queue_mutex_lock();
1221 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1222 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1223 pthread_mutex_unlock(&surface_queue->lock);
1224 _tbm_surf_queue_mutex_unlock();
1228 pthread_mutex_unlock(&surface_queue->lock);
1229 _tbm_surf_queue_mutex_unlock();
1233 pthread_mutex_unlock(&surface_queue->lock);
1234 _tbm_surf_queue_mutex_unlock();
1238 tbm_surface_queue_error_e
1239 tbm_surface_queue_release(tbm_surface_queue_h
1240 surface_queue, tbm_surface_h surface)
1245 _tbm_surf_queue_mutex_lock();
1247 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1248 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1249 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1250 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1252 pthread_mutex_lock(&surface_queue->lock);
1254 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1256 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1257 if (node == NULL || queue_type != NODE_LIST) {
1258 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1260 pthread_mutex_unlock(&surface_queue->lock);
1262 _tbm_surf_queue_mutex_unlock();
1265 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1267 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1270 if (surface_queue->queue_size < surface_queue->num_attached) {
1271 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1273 if (surface_queue->impl && surface_queue->impl->need_detach)
1274 surface_queue->impl->need_detach(surface_queue, node);
1276 _tbm_surface_queue_detach(surface_queue, surface);
1278 pthread_mutex_unlock(&surface_queue->lock);
1280 _tbm_surf_queue_mutex_unlock();
1281 return TBM_SURFACE_QUEUE_ERROR_NONE;
1284 if (surface_queue->impl && surface_queue->impl->release)
1285 surface_queue->impl->release(surface_queue, node);
1287 _tbm_surface_queue_release(surface_queue, node, 1);
1289 if (_queue_is_empty(&surface_queue->free_queue)) {
1290 pthread_mutex_unlock(&surface_queue->lock);
1292 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1293 _tbm_surf_queue_mutex_unlock();
1294 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1297 node->type = QUEUE_NODE_TYPE_RELEASE;
1299 pthread_mutex_unlock(&surface_queue->lock);
1300 pthread_cond_signal(&surface_queue->free_cond);
1302 _tbm_surf_queue_mutex_unlock();
1304 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1306 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1308 return TBM_SURFACE_QUEUE_ERROR_NONE;
1311 tbm_surface_queue_error_e
1312 tbm_surface_queue_acquire(tbm_surface_queue_h
1313 surface_queue, tbm_surface_h *surface)
1317 _tbm_surf_queue_mutex_lock();
1321 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1322 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1323 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1324 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1326 pthread_mutex_lock(&surface_queue->lock);
1328 if (surface_queue->impl && surface_queue->impl->acquire)
1329 node = surface_queue->impl->acquire(surface_queue);
1331 node = _tbm_surface_queue_acquire(surface_queue);
1333 if (node == NULL || node->surface == NULL) {
1334 TBM_LOG_E("_queue_node_pop_front failed\n");
1335 pthread_mutex_unlock(&surface_queue->lock);
1337 _tbm_surf_queue_mutex_unlock();
1338 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1341 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1343 *surface = node->surface;
1345 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1347 pthread_mutex_unlock(&surface_queue->lock);
1349 _tbm_surf_queue_mutex_unlock();
1352 tbm_surface_internal_dump_buffer(*surface, "acquire");
1354 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1356 return TBM_SURFACE_QUEUE_ERROR_NONE;
1360 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1362 _tbm_surf_queue_mutex_lock();
1364 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1366 pthread_mutex_lock(&surface_queue->lock);
1368 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1370 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1371 pthread_mutex_unlock(&surface_queue->lock);
1372 _tbm_surf_queue_mutex_unlock();
1376 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1377 QUEUE_NODE_TYPE_DEQUEUE)) {
1378 _tbm_surf_queue_mutex_unlock();
1379 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1380 _tbm_surf_queue_mutex_lock();
1382 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1383 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1384 pthread_mutex_unlock(&surface_queue->lock);
1385 _tbm_surf_queue_mutex_unlock();
1389 pthread_mutex_unlock(&surface_queue->lock);
1390 _tbm_surf_queue_mutex_unlock();
1394 pthread_mutex_unlock(&surface_queue->lock);
1395 _tbm_surf_queue_mutex_unlock();
1400 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1402 queue_node *node = NULL, *tmp;
1404 _tbm_surf_queue_mutex_lock();
1406 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1408 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1410 LIST_DEL(&surface_queue->item_link);
1412 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1413 _queue_delete_node(surface_queue, node);
1415 if (surface_queue->impl && surface_queue->impl->destroy)
1416 surface_queue->impl->destroy(surface_queue);
1418 _notify_emit(surface_queue, &surface_queue->destory_noti);
1420 _notify_remove_all(&surface_queue->destory_noti);
1421 _notify_remove_all(&surface_queue->dequeuable_noti);
1422 _notify_remove_all(&surface_queue->dequeue_noti);
1423 _notify_remove_all(&surface_queue->can_dequeue_noti);
1424 _notify_remove_all(&surface_queue->acquirable_noti);
1425 _notify_remove_all(&surface_queue->reset_noti);
1426 _trace_remove_all(&surface_queue->trace_noti);
1428 pthread_mutex_destroy(&surface_queue->lock);
1430 free(surface_queue);
1432 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1433 _deinit_tbm_surf_queue_bufmgr();
1435 _tbm_surf_queue_mutex_unlock();
1438 tbm_surface_queue_error_e
1439 tbm_surface_queue_reset(tbm_surface_queue_h
1440 surface_queue, int width, int height, int format)
1442 queue_node *node = NULL, *tmp;
1444 _tbm_surf_queue_mutex_lock();
1446 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1447 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1449 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1451 if (width == surface_queue->width && height == surface_queue->height &&
1452 format == surface_queue->format) {
1453 _tbm_surf_queue_mutex_unlock();
1454 return TBM_SURFACE_QUEUE_ERROR_NONE;
1457 pthread_mutex_lock(&surface_queue->lock);
1459 surface_queue->width = width;
1460 surface_queue->height = height;
1461 surface_queue->format = format;
1463 /* Destory surface and Push to free_queue */
1464 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1465 _queue_delete_node(surface_queue, node);
1468 _queue_init(&surface_queue->free_queue);
1469 _queue_init(&surface_queue->dirty_queue);
1470 LIST_INITHEAD(&surface_queue->list);
1472 surface_queue->num_attached = 0;
1474 if (surface_queue->impl && surface_queue->impl->reset)
1475 surface_queue->impl->reset(surface_queue);
1477 pthread_mutex_unlock(&surface_queue->lock);
1478 pthread_cond_signal(&surface_queue->free_cond);
1480 _tbm_surf_queue_mutex_unlock();
1482 _notify_emit(surface_queue, &surface_queue->reset_noti);
1484 return TBM_SURFACE_QUEUE_ERROR_NONE;
1487 tbm_surface_queue_error_e
1488 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1490 _tbm_surf_queue_mutex_lock();
1492 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1493 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1495 _tbm_surf_queue_mutex_unlock();
1497 _notify_emit(surface_queue, &surface_queue->reset_noti);
1499 return TBM_SURFACE_QUEUE_ERROR_NONE;
1502 tbm_surface_queue_error_e
1503 tbm_surface_queue_set_size(tbm_surface_queue_h
1504 surface_queue, int queue_size, int flush)
1506 queue_node *node = NULL, *tmp;
1508 _tbm_surf_queue_mutex_lock();
1510 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1511 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1512 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1513 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1515 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1517 if ((surface_queue->queue_size == queue_size) && !flush) {
1518 _tbm_surf_queue_mutex_unlock();
1519 return TBM_SURFACE_QUEUE_ERROR_NONE;
1522 pthread_mutex_lock(&surface_queue->lock);
1525 /* Destory surface and Push to free_queue */
1526 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1527 _queue_delete_node(surface_queue, node);
1530 _queue_init(&surface_queue->free_queue);
1531 _queue_init(&surface_queue->dirty_queue);
1532 LIST_INITHEAD(&surface_queue->list);
1534 surface_queue->num_attached = 0;
1535 surface_queue->queue_size = queue_size;
1537 if (surface_queue->impl && surface_queue->impl->reset)
1538 surface_queue->impl->reset(surface_queue);
1540 pthread_mutex_unlock(&surface_queue->lock);
1541 pthread_cond_signal(&surface_queue->free_cond);
1543 _tbm_surf_queue_mutex_unlock();
1545 _notify_emit(surface_queue, &surface_queue->reset_noti);
1547 return TBM_SURFACE_QUEUE_ERROR_NONE;
1549 if (surface_queue->queue_size > queue_size) {
1550 int need_del = surface_queue->queue_size - queue_size;
1552 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1553 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1555 if (surface_queue->impl && surface_queue->impl->need_detach)
1556 surface_queue->impl->need_detach(surface_queue, node);
1558 _tbm_surface_queue_detach(surface_queue, node->surface);
1566 surface_queue->queue_size = queue_size;
1568 pthread_mutex_unlock(&surface_queue->lock);
1570 _tbm_surf_queue_mutex_unlock();
1572 return TBM_SURFACE_QUEUE_ERROR_NONE;
1576 tbm_surface_queue_error_e
1577 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1579 queue_node *node = NULL;
1581 _tbm_surf_queue_mutex_lock();
1583 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1584 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1586 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1588 if (surface_queue->num_attached == 0) {
1589 _tbm_surf_queue_mutex_unlock();
1590 return TBM_SURFACE_QUEUE_ERROR_NONE;
1593 pthread_mutex_lock(&surface_queue->lock);
1595 /* Destory surface in free_queue */
1596 while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1597 if (surface_queue->impl && surface_queue->impl->need_detach)
1598 surface_queue->impl->need_detach(surface_queue, node);
1600 _tbm_surface_queue_detach(surface_queue, node->surface);
1604 _queue_init(&surface_queue->free_queue);
1606 pthread_mutex_unlock(&surface_queue->lock);
1607 _tbm_surf_queue_mutex_unlock();
1609 return TBM_SURFACE_QUEUE_ERROR_NONE;
1612 tbm_surface_queue_error_e
1613 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1615 queue_node *node = NULL, *tmp;
1617 _tbm_surf_queue_mutex_lock();
1619 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1620 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1622 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1624 if (surface_queue->num_attached == 0) {
1625 _tbm_surf_queue_mutex_unlock();
1626 return TBM_SURFACE_QUEUE_ERROR_NONE;
1629 pthread_mutex_lock(&surface_queue->lock);
1631 /* Destory surface and Push to free_queue */
1632 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1633 _queue_delete_node(surface_queue, node);
1636 _queue_init(&surface_queue->free_queue);
1637 _queue_init(&surface_queue->dirty_queue);
1638 LIST_INITHEAD(&surface_queue->list);
1640 surface_queue->num_attached = 0;
1642 if (surface_queue->impl && surface_queue->impl->reset)
1643 surface_queue->impl->reset(surface_queue);
1645 pthread_mutex_unlock(&surface_queue->lock);
1646 pthread_cond_signal(&surface_queue->free_cond);
1648 _tbm_surf_queue_mutex_unlock();
1650 _notify_emit(surface_queue, &surface_queue->reset_noti);
1652 return TBM_SURFACE_QUEUE_ERROR_NONE;
1655 tbm_surface_queue_error_e
1656 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1657 tbm_surface_h *surfaces, int *num)
1659 queue_node *node = NULL;
1661 _tbm_surf_queue_mutex_lock();
1665 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1666 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1667 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1668 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1670 pthread_mutex_lock(&surface_queue->lock);
1672 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1674 surfaces[*num] = node->surface;
1679 pthread_mutex_unlock(&surface_queue->lock);
1681 _tbm_surf_queue_mutex_unlock();
1683 return TBM_SURFACE_QUEUE_ERROR_NONE;
1686 tbm_surface_queue_error_e
1687 tbm_surface_queue_get_trace_surface_num(
1688 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1690 _tbm_surf_queue_mutex_lock();
1694 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1695 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1696 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1697 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1699 pthread_mutex_lock(&surface_queue->lock);
1702 case TBM_SURFACE_QUEUE_TRACE_NONE:
1705 case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1706 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1708 case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1709 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1711 case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1712 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1714 case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1715 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1719 pthread_mutex_unlock(&surface_queue->lock);
1721 _tbm_surf_queue_mutex_unlock();
1723 return TBM_SURFACE_QUEUE_ERROR_NONE;
1728 } tbm_queue_default;
1731 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1733 free(surface_queue->impl_data);
1737 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1739 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1740 tbm_surface_h surface;
1742 if (surface_queue->queue_size == surface_queue->num_attached)
1745 if (surface_queue->alloc_cb) {
1746 pthread_mutex_unlock(&surface_queue->lock);
1747 _tbm_surf_queue_mutex_unlock();
1748 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1749 _tbm_surf_queue_mutex_lock();
1750 pthread_mutex_lock(&surface_queue->lock);
1756 tbm_surface_internal_ref(surface);
1758 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1759 surface_queue->height,
1760 surface_queue->format,
1762 TBM_RETURN_IF_FAIL(surface != NULL);
1765 _tbm_surface_queue_attach(surface_queue, surface);
1766 tbm_surface_internal_unref(surface);
1769 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1770 NULL, /*__tbm_queue_default_init*/
1771 NULL, /*__tbm_queue_default_reset*/
1772 __tbm_queue_default_destroy,
1773 __tbm_queue_default_need_attach,
1774 NULL, /*__tbm_queue_default_enqueue*/
1775 NULL, /*__tbm_queue_default_release*/
1776 NULL, /*__tbm_queue_default_dequeue*/
1777 NULL, /*__tbm_queue_default_acquire*/
1778 NULL, /*__tbm_queue_default_need_detach*/
1782 tbm_surface_queue_create(int queue_size, int width,
1783 int height, int format, int flags)
1785 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1786 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1787 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1788 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1790 _tbm_surf_queue_mutex_lock();
1792 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1793 sizeof(struct _tbm_surface_queue));
1794 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1796 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1798 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1799 sizeof(tbm_queue_default));
1801 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1802 free(surface_queue);
1803 _tbm_surf_queue_mutex_unlock();
1807 data->flags = flags;
1808 _tbm_surface_queue_init(surface_queue,
1810 width, height, format,
1811 &tbm_queue_default_impl, data);
1813 _tbm_surf_queue_mutex_unlock();
1815 return surface_queue;
1821 } tbm_queue_sequence;
1824 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1826 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1828 _queue_init(&data->dequeue_list);
1832 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1834 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1836 _queue_init(&data->dequeue_list);
1840 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1842 free(surface_queue->impl_data);
1846 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1848 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1849 tbm_surface_h surface;
1851 if (surface_queue->queue_size == surface_queue->num_attached)
1854 if (surface_queue->alloc_cb) {
1855 pthread_mutex_unlock(&surface_queue->lock);
1856 _tbm_surf_queue_mutex_unlock();
1857 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1858 _tbm_surf_queue_mutex_lock();
1859 pthread_mutex_lock(&surface_queue->lock);
1865 tbm_surface_internal_ref(surface);
1867 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1868 surface_queue->height,
1869 surface_queue->format,
1871 TBM_RETURN_IF_FAIL(surface != NULL);
1874 _tbm_surface_queue_attach(surface_queue, surface);
1875 tbm_surface_internal_unref(surface);
1879 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1882 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1883 queue_node *next = NULL, *tmp;
1885 node->priv_flags = 0;
1887 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1888 if (next->priv_flags)
1890 _queue_node_pop(&data->dequeue_list, next);
1891 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1896 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1899 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1902 node = _tbm_surface_queue_dequeue(surface_queue);
1904 _queue_node_push_back(&data->dequeue_list, node);
1905 node->priv_flags = 1;
1911 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1912 __tbm_queue_sequence_init,
1913 __tbm_queue_sequence_reset,
1914 __tbm_queue_sequence_destroy,
1915 __tbm_queue_sequence_need_attach,
1916 __tbm_queue_sequence_enqueue,
1917 NULL, /*__tbm_queue_sequence_release*/
1918 __tbm_queue_sequence_dequeue,
1919 NULL, /*__tbm_queue_sequence_acquire*/
1920 NULL, /*__tbm_queue_sequence_need_dettach*/
1924 tbm_surface_queue_sequence_create(int queue_size, int width,
1925 int height, int format, int flags)
1927 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1928 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1929 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1930 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1932 _tbm_surf_queue_mutex_lock();
1934 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1935 sizeof(struct _tbm_surface_queue));
1936 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1938 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1940 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1941 sizeof(tbm_queue_sequence));
1943 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
1944 free(surface_queue);
1945 _tbm_surf_queue_mutex_unlock();
1949 data->flags = flags;
1950 _tbm_surface_queue_init(surface_queue,
1952 width, height, format,
1953 &tbm_queue_sequence_impl, data);
1955 _tbm_surf_queue_mutex_unlock();
1957 return surface_queue;
1959 /* LCOV_EXCL_STOP */