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();
1098 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1101 if (surface_queue->impl && surface_queue->impl->enqueue)
1102 surface_queue->impl->enqueue(surface_queue, node);
1104 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1106 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1107 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1108 pthread_mutex_unlock(&surface_queue->lock);
1110 _tbm_surf_queue_mutex_unlock();
1111 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1114 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1116 pthread_mutex_unlock(&surface_queue->lock);
1117 pthread_cond_signal(&surface_queue->dirty_cond);
1119 _tbm_surf_queue_mutex_unlock();
1121 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1123 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1125 return TBM_SURFACE_QUEUE_ERROR_NONE;
1128 tbm_surface_queue_error_e
1129 tbm_surface_queue_dequeue(tbm_surface_queue_h
1130 surface_queue, tbm_surface_h *surface)
1134 _tbm_surf_queue_mutex_lock();
1138 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1139 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1140 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1141 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1143 pthread_mutex_lock(&surface_queue->lock);
1145 if (surface_queue->impl && surface_queue->impl->dequeue)
1146 node = surface_queue->impl->dequeue(surface_queue);
1148 node = _tbm_surface_queue_dequeue(surface_queue);
1150 if (node == NULL || node->surface == NULL) {
1151 TBM_LOG_E("_queue_node_pop_front failed\n");
1152 pthread_mutex_unlock(&surface_queue->lock);
1154 _tbm_surf_queue_mutex_unlock();
1155 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1158 node->type = QUEUE_NODE_TYPE_DEQUEUE;
1159 *surface = node->surface;
1161 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1163 pthread_mutex_unlock(&surface_queue->lock);
1165 _tbm_surf_queue_mutex_unlock();
1167 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1169 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1171 return TBM_SURFACE_QUEUE_ERROR_NONE;
1175 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1177 _tbm_surf_queue_mutex_lock();
1179 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1181 _tbm_surf_queue_mutex_unlock();
1183 _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1185 _tbm_surf_queue_mutex_lock();
1187 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1189 pthread_mutex_lock(&surface_queue->lock);
1191 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1193 if (_queue_is_empty(&surface_queue->free_queue)) {
1194 if (surface_queue->impl && surface_queue->impl->need_attach)
1195 surface_queue->impl->need_attach(surface_queue);
1197 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1198 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1199 _tbm_surf_queue_mutex_unlock();
1204 if (!_queue_is_empty(&surface_queue->free_queue)) {
1205 pthread_mutex_unlock(&surface_queue->lock);
1206 _tbm_surf_queue_mutex_unlock();
1210 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1211 QUEUE_NODE_TYPE_ACQUIRE)) {
1212 _tbm_surf_queue_mutex_unlock();
1213 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1214 _tbm_surf_queue_mutex_lock();
1216 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1217 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1218 pthread_mutex_unlock(&surface_queue->lock);
1219 _tbm_surf_queue_mutex_unlock();
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 tbm_surface_queue_error_e
1234 tbm_surface_queue_release(tbm_surface_queue_h
1235 surface_queue, tbm_surface_h surface)
1240 _tbm_surf_queue_mutex_lock();
1242 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1243 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1244 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1245 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1247 pthread_mutex_lock(&surface_queue->lock);
1249 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1251 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1252 if (node == NULL || queue_type != NODE_LIST) {
1253 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1255 pthread_mutex_unlock(&surface_queue->lock);
1257 _tbm_surf_queue_mutex_unlock();
1258 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1261 if (surface_queue->queue_size < surface_queue->num_attached) {
1262 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1264 if (surface_queue->impl && surface_queue->impl->need_detach)
1265 surface_queue->impl->need_detach(surface_queue, node);
1267 _tbm_surface_queue_detach(surface_queue, surface);
1269 pthread_mutex_unlock(&surface_queue->lock);
1271 _tbm_surf_queue_mutex_unlock();
1272 return TBM_SURFACE_QUEUE_ERROR_NONE;
1275 if (surface_queue->impl && surface_queue->impl->release)
1276 surface_queue->impl->release(surface_queue, node);
1278 _tbm_surface_queue_release(surface_queue, node, 1);
1280 if (_queue_is_empty(&surface_queue->free_queue)) {
1281 pthread_mutex_unlock(&surface_queue->lock);
1283 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1284 _tbm_surf_queue_mutex_unlock();
1285 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1288 node->type = QUEUE_NODE_TYPE_RELEASE;
1290 pthread_mutex_unlock(&surface_queue->lock);
1291 pthread_cond_signal(&surface_queue->free_cond);
1293 _tbm_surf_queue_mutex_unlock();
1295 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1297 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1299 return TBM_SURFACE_QUEUE_ERROR_NONE;
1302 tbm_surface_queue_error_e
1303 tbm_surface_queue_acquire(tbm_surface_queue_h
1304 surface_queue, tbm_surface_h *surface)
1308 _tbm_surf_queue_mutex_lock();
1312 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1313 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1314 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1315 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1317 pthread_mutex_lock(&surface_queue->lock);
1319 if (surface_queue->impl && surface_queue->impl->acquire)
1320 node = surface_queue->impl->acquire(surface_queue);
1322 node = _tbm_surface_queue_acquire(surface_queue);
1324 if (node == NULL || node->surface == NULL) {
1325 TBM_LOG_E("_queue_node_pop_front failed\n");
1326 pthread_mutex_unlock(&surface_queue->lock);
1328 _tbm_surf_queue_mutex_unlock();
1329 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1332 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1334 *surface = node->surface;
1336 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1338 pthread_mutex_unlock(&surface_queue->lock);
1340 _tbm_surf_queue_mutex_unlock();
1343 tbm_surface_internal_dump_buffer(*surface, "acquire");
1345 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1347 return TBM_SURFACE_QUEUE_ERROR_NONE;
1351 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1353 _tbm_surf_queue_mutex_lock();
1355 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1357 pthread_mutex_lock(&surface_queue->lock);
1359 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1361 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1362 pthread_mutex_unlock(&surface_queue->lock);
1363 _tbm_surf_queue_mutex_unlock();
1367 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1368 QUEUE_NODE_TYPE_DEQUEUE)) {
1369 _tbm_surf_queue_mutex_unlock();
1370 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1371 _tbm_surf_queue_mutex_lock();
1373 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1374 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1375 pthread_mutex_unlock(&surface_queue->lock);
1376 _tbm_surf_queue_mutex_unlock();
1380 pthread_mutex_unlock(&surface_queue->lock);
1381 _tbm_surf_queue_mutex_unlock();
1385 pthread_mutex_unlock(&surface_queue->lock);
1386 _tbm_surf_queue_mutex_unlock();
1391 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1393 queue_node *node = NULL, *tmp;
1395 _tbm_surf_queue_mutex_lock();
1397 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1399 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1401 LIST_DEL(&surface_queue->item_link);
1403 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1404 _queue_delete_node(surface_queue, node);
1406 if (surface_queue->impl && surface_queue->impl->destroy)
1407 surface_queue->impl->destroy(surface_queue);
1409 _notify_emit(surface_queue, &surface_queue->destory_noti);
1411 _notify_remove_all(&surface_queue->destory_noti);
1412 _notify_remove_all(&surface_queue->dequeuable_noti);
1413 _notify_remove_all(&surface_queue->dequeue_noti);
1414 _notify_remove_all(&surface_queue->can_dequeue_noti);
1415 _notify_remove_all(&surface_queue->acquirable_noti);
1416 _notify_remove_all(&surface_queue->reset_noti);
1417 _trace_remove_all(&surface_queue->trace_noti);
1419 pthread_mutex_destroy(&surface_queue->lock);
1421 free(surface_queue);
1423 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1424 _deinit_tbm_surf_queue_bufmgr();
1426 _tbm_surf_queue_mutex_unlock();
1429 tbm_surface_queue_error_e
1430 tbm_surface_queue_reset(tbm_surface_queue_h
1431 surface_queue, int width, int height, int format)
1433 queue_node *node = NULL, *tmp;
1435 _tbm_surf_queue_mutex_lock();
1437 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1438 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1440 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1442 if (width == surface_queue->width && height == surface_queue->height &&
1443 format == surface_queue->format) {
1444 _tbm_surf_queue_mutex_unlock();
1445 return TBM_SURFACE_QUEUE_ERROR_NONE;
1448 pthread_mutex_lock(&surface_queue->lock);
1450 surface_queue->width = width;
1451 surface_queue->height = height;
1452 surface_queue->format = format;
1454 /* Destory surface and Push to free_queue */
1455 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1456 _queue_delete_node(surface_queue, node);
1459 _queue_init(&surface_queue->free_queue);
1460 _queue_init(&surface_queue->dirty_queue);
1461 LIST_INITHEAD(&surface_queue->list);
1463 surface_queue->num_attached = 0;
1465 if (surface_queue->impl && surface_queue->impl->reset)
1466 surface_queue->impl->reset(surface_queue);
1468 pthread_mutex_unlock(&surface_queue->lock);
1469 pthread_cond_signal(&surface_queue->free_cond);
1471 _tbm_surf_queue_mutex_unlock();
1473 _notify_emit(surface_queue, &surface_queue->reset_noti);
1475 return TBM_SURFACE_QUEUE_ERROR_NONE;
1478 tbm_surface_queue_error_e
1479 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1481 _tbm_surf_queue_mutex_lock();
1483 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1484 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1486 _tbm_surf_queue_mutex_unlock();
1488 _notify_emit(surface_queue, &surface_queue->reset_noti);
1490 return TBM_SURFACE_QUEUE_ERROR_NONE;
1493 tbm_surface_queue_error_e
1494 tbm_surface_queue_set_size(tbm_surface_queue_h
1495 surface_queue, int queue_size, int flush)
1497 queue_node *node = NULL, *tmp;
1499 _tbm_surf_queue_mutex_lock();
1501 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1502 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1503 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1504 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1506 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1508 if ((surface_queue->queue_size == queue_size) && !flush) {
1509 _tbm_surf_queue_mutex_unlock();
1510 return TBM_SURFACE_QUEUE_ERROR_NONE;
1513 pthread_mutex_lock(&surface_queue->lock);
1516 /* Destory surface and Push to free_queue */
1517 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1518 _queue_delete_node(surface_queue, node);
1521 _queue_init(&surface_queue->free_queue);
1522 _queue_init(&surface_queue->dirty_queue);
1523 LIST_INITHEAD(&surface_queue->list);
1525 surface_queue->num_attached = 0;
1526 surface_queue->queue_size = queue_size;
1528 if (surface_queue->impl && surface_queue->impl->reset)
1529 surface_queue->impl->reset(surface_queue);
1531 pthread_mutex_unlock(&surface_queue->lock);
1532 pthread_cond_signal(&surface_queue->free_cond);
1534 _tbm_surf_queue_mutex_unlock();
1536 _notify_emit(surface_queue, &surface_queue->reset_noti);
1538 return TBM_SURFACE_QUEUE_ERROR_NONE;
1540 if (surface_queue->queue_size > queue_size) {
1541 int need_del = surface_queue->queue_size - queue_size;
1543 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1544 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1546 if (surface_queue->impl && surface_queue->impl->need_detach)
1547 surface_queue->impl->need_detach(surface_queue, node);
1549 _tbm_surface_queue_detach(surface_queue, node->surface);
1557 surface_queue->queue_size = queue_size;
1559 pthread_mutex_unlock(&surface_queue->lock);
1561 _tbm_surf_queue_mutex_unlock();
1563 return TBM_SURFACE_QUEUE_ERROR_NONE;
1567 tbm_surface_queue_error_e
1568 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1570 queue_node *node = NULL;
1572 _tbm_surf_queue_mutex_lock();
1574 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1575 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1577 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1579 if (surface_queue->num_attached == 0) {
1580 _tbm_surf_queue_mutex_unlock();
1581 return TBM_SURFACE_QUEUE_ERROR_NONE;
1584 pthread_mutex_lock(&surface_queue->lock);
1586 /* Destory surface in free_queue */
1587 while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1588 if (surface_queue->impl && surface_queue->impl->need_detach)
1589 surface_queue->impl->need_detach(surface_queue, node);
1591 _tbm_surface_queue_detach(surface_queue, node->surface);
1595 _queue_init(&surface_queue->free_queue);
1597 pthread_mutex_unlock(&surface_queue->lock);
1598 _tbm_surf_queue_mutex_unlock();
1600 return TBM_SURFACE_QUEUE_ERROR_NONE;
1603 tbm_surface_queue_error_e
1604 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1606 queue_node *node = NULL, *tmp;
1608 _tbm_surf_queue_mutex_lock();
1610 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1611 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1613 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1615 if (surface_queue->num_attached == 0) {
1616 _tbm_surf_queue_mutex_unlock();
1617 return TBM_SURFACE_QUEUE_ERROR_NONE;
1620 pthread_mutex_lock(&surface_queue->lock);
1622 /* Destory surface and Push to free_queue */
1623 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1624 _queue_delete_node(surface_queue, node);
1627 _queue_init(&surface_queue->free_queue);
1628 _queue_init(&surface_queue->dirty_queue);
1629 LIST_INITHEAD(&surface_queue->list);
1631 surface_queue->num_attached = 0;
1633 if (surface_queue->impl && surface_queue->impl->reset)
1634 surface_queue->impl->reset(surface_queue);
1636 pthread_mutex_unlock(&surface_queue->lock);
1637 pthread_cond_signal(&surface_queue->free_cond);
1639 _tbm_surf_queue_mutex_unlock();
1641 _notify_emit(surface_queue, &surface_queue->reset_noti);
1643 return TBM_SURFACE_QUEUE_ERROR_NONE;
1646 tbm_surface_queue_error_e
1647 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1648 tbm_surface_h *surfaces, int *num)
1650 queue_node *node = NULL;
1652 _tbm_surf_queue_mutex_lock();
1656 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1657 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1658 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1659 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1661 pthread_mutex_lock(&surface_queue->lock);
1663 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1665 surfaces[*num] = node->surface;
1670 pthread_mutex_unlock(&surface_queue->lock);
1672 _tbm_surf_queue_mutex_unlock();
1674 return TBM_SURFACE_QUEUE_ERROR_NONE;
1677 tbm_surface_queue_error_e
1678 tbm_surface_queue_get_trace_surface_num(
1679 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1681 _tbm_surf_queue_mutex_lock();
1685 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1686 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1687 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1688 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1690 pthread_mutex_lock(&surface_queue->lock);
1693 case TBM_SURFACE_QUEUE_TRACE_NONE:
1696 case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1697 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1699 case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1700 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1702 case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1703 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1705 case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1706 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1710 pthread_mutex_unlock(&surface_queue->lock);
1712 _tbm_surf_queue_mutex_unlock();
1714 return TBM_SURFACE_QUEUE_ERROR_NONE;
1719 } tbm_queue_default;
1722 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1724 free(surface_queue->impl_data);
1728 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1730 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1731 tbm_surface_h surface;
1733 if (surface_queue->queue_size == surface_queue->num_attached)
1736 if (surface_queue->alloc_cb) {
1737 pthread_mutex_unlock(&surface_queue->lock);
1738 _tbm_surf_queue_mutex_unlock();
1739 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1740 _tbm_surf_queue_mutex_lock();
1741 pthread_mutex_lock(&surface_queue->lock);
1747 tbm_surface_internal_ref(surface);
1749 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1750 surface_queue->height,
1751 surface_queue->format,
1753 TBM_RETURN_IF_FAIL(surface != NULL);
1756 _tbm_surface_queue_attach(surface_queue, surface);
1757 tbm_surface_internal_unref(surface);
1760 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1761 NULL, /*__tbm_queue_default_init*/
1762 NULL, /*__tbm_queue_default_reset*/
1763 __tbm_queue_default_destroy,
1764 __tbm_queue_default_need_attach,
1765 NULL, /*__tbm_queue_default_enqueue*/
1766 NULL, /*__tbm_queue_default_release*/
1767 NULL, /*__tbm_queue_default_dequeue*/
1768 NULL, /*__tbm_queue_default_acquire*/
1769 NULL, /*__tbm_queue_default_need_detach*/
1773 tbm_surface_queue_create(int queue_size, int width,
1774 int height, int format, int flags)
1776 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1777 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1778 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1779 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1781 _tbm_surf_queue_mutex_lock();
1783 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1784 sizeof(struct _tbm_surface_queue));
1785 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1787 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1789 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1790 sizeof(tbm_queue_default));
1792 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1793 free(surface_queue);
1794 _tbm_surf_queue_mutex_unlock();
1798 data->flags = flags;
1799 _tbm_surface_queue_init(surface_queue,
1801 width, height, format,
1802 &tbm_queue_default_impl, data);
1804 _tbm_surf_queue_mutex_unlock();
1806 return surface_queue;
1812 } tbm_queue_sequence;
1815 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1817 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1819 _queue_init(&data->dequeue_list);
1823 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1825 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1827 _queue_init(&data->dequeue_list);
1831 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1833 free(surface_queue->impl_data);
1837 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1839 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1840 tbm_surface_h surface;
1842 if (surface_queue->queue_size == surface_queue->num_attached)
1845 if (surface_queue->alloc_cb) {
1846 pthread_mutex_unlock(&surface_queue->lock);
1847 _tbm_surf_queue_mutex_unlock();
1848 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1849 _tbm_surf_queue_mutex_lock();
1850 pthread_mutex_lock(&surface_queue->lock);
1856 tbm_surface_internal_ref(surface);
1858 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1859 surface_queue->height,
1860 surface_queue->format,
1862 TBM_RETURN_IF_FAIL(surface != NULL);
1865 _tbm_surface_queue_attach(surface_queue, surface);
1866 tbm_surface_internal_unref(surface);
1870 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1873 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1874 queue_node *next = NULL, *tmp;
1876 node->priv_flags = 0;
1878 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1879 if (next->priv_flags)
1881 _queue_node_pop(&data->dequeue_list, next);
1882 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1887 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1890 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1893 node = _tbm_surface_queue_dequeue(surface_queue);
1895 _queue_node_push_back(&data->dequeue_list, node);
1896 node->priv_flags = 1;
1902 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1903 __tbm_queue_sequence_init,
1904 __tbm_queue_sequence_reset,
1905 __tbm_queue_sequence_destroy,
1906 __tbm_queue_sequence_need_attach,
1907 __tbm_queue_sequence_enqueue,
1908 NULL, /*__tbm_queue_sequence_release*/
1909 __tbm_queue_sequence_dequeue,
1910 NULL, /*__tbm_queue_sequence_acquire*/
1911 NULL, /*__tbm_queue_sequence_need_dettach*/
1915 tbm_surface_queue_sequence_create(int queue_size, int width,
1916 int height, int format, int flags)
1918 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1919 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1920 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1921 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1923 _tbm_surf_queue_mutex_lock();
1925 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1926 sizeof(struct _tbm_surface_queue));
1927 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1929 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1931 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1932 sizeof(tbm_queue_sequence));
1934 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
1935 free(surface_queue);
1936 _tbm_surf_queue_mutex_unlock();
1940 data->flags = flags;
1941 _tbm_surface_queue_init(surface_queue,
1943 width, height, format,
1944 &tbm_queue_sequence_impl, data);
1946 _tbm_surf_queue_mutex_unlock();
1948 return surface_queue;
1950 /* LCOV_EXCL_STOP */