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*/
105 struct list_head link;
107 tbm_surface_queue_notify_cb cb;
112 struct list_head link;
114 tbm_surface_queue_trace_cb cb;
118 typedef struct _tbm_surface_queue_interface {
119 void (*init)(tbm_surface_queue_h queue);
120 void (*reset)(tbm_surface_queue_h queue);
121 void (*destroy)(tbm_surface_queue_h queue);
122 void (*need_attach)(tbm_surface_queue_h queue);
124 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
125 void (*release)(tbm_surface_queue_h queue, queue_node *node);
126 queue_node *(*dequeue)(tbm_surface_queue_h queue);
127 queue_node *(*acquire)(tbm_surface_queue_h queue);
128 void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
129 } tbm_surface_queue_interface;
131 struct _tbm_surface_queue {
140 struct list_head list;
142 struct list_head destory_noti;
143 struct list_head dequeuable_noti;
144 struct list_head dequeue_noti;
145 struct list_head can_dequeue_noti;
146 struct list_head acquirable_noti;
147 struct list_head reset_noti;
148 struct list_head trace_noti;
150 pthread_mutex_t lock;
151 pthread_cond_t free_cond;
152 pthread_cond_t dirty_cond;
154 const tbm_surface_queue_interface *impl;
157 //For external buffer allocation
158 tbm_surface_alloc_cb alloc_cb;
159 tbm_surface_free_cb free_cb;
162 struct list_head item_link; /* link of surface queue */
168 _tbm_surf_queue_mutex_init(void)
170 static bool tbm_surf_queue_mutex_init = false;
172 if (tbm_surf_queue_mutex_init)
175 if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
176 TBM_LOG_E("fail: pthread_mutex_init\n");
180 tbm_surf_queue_mutex_init = true;
186 _tbm_surf_queue_mutex_lock(void)
188 if (!_tbm_surf_queue_mutex_init()) {
189 TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n");
193 pthread_mutex_lock(&tbm_surf_queue_lock);
197 _tbm_surf_queue_mutex_unlock(void)
199 pthread_mutex_unlock(&tbm_surf_queue_lock);
203 _init_tbm_surf_queue_bufmgr(void)
205 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
209 _deinit_tbm_surf_queue_bufmgr(void)
211 if (!g_surf_queue_bufmgr)
214 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
215 g_surf_queue_bufmgr = NULL;
219 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
221 tbm_surface_queue_h old_data = NULL;
223 if (surface_queue == NULL) {
224 TBM_LOG_E("error: surface_queue is NULL.\n");
228 if (g_surf_queue_bufmgr == NULL) {
229 TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n");
233 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
234 TBM_LOG_E("error: surf_queue_list is empty\n");
238 LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
240 if (old_data == surface_queue) {
241 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
246 TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
252 _queue_node_create(void)
254 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
256 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
262 _queue_node_delete(queue_node *node)
264 LIST_DEL(&node->item_link);
265 LIST_DEL(&node->link);
270 _queue_is_empty(queue *queue)
272 if (LIST_IS_EMPTY(&queue->head))
279 _queue_node_push_back(queue *queue, queue_node *node)
281 LIST_ADDTAIL(&node->item_link, &queue->head);
286 _queue_node_push_front(queue *queue, queue_node *node)
288 LIST_ADD(&node->item_link, &queue->head);
293 _queue_node_pop_front(queue *queue)
297 if (!queue->head.next) return NULL;
298 if (!queue->count) return NULL;
300 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
302 LIST_DELINIT(&node->item_link);
309 _queue_node_pop(queue *queue, queue_node *node)
311 LIST_DELINIT(&node->item_link);
318 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
319 tbm_surface_h surface, int *out_type)
321 queue_node *node = NULL;
324 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
328 if (type & FREE_QUEUE) {
329 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
331 if (node->surface == surface) {
333 *out_type = FREE_QUEUE;
340 if (type & DIRTY_QUEUE) {
341 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
343 if (node->surface == surface) {
345 *out_type = DIRTY_QUEUE;
352 if (type & NODE_LIST) {
353 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
354 if (node->surface == surface) {
356 *out_type = NODE_LIST;
363 TBM_LOG_E("fail to get the queue_node.\n");
369 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
372 if (surface_queue->free_cb) {
373 surface_queue->free_cb(surface_queue,
374 surface_queue->alloc_cb_data,
378 tbm_surface_destroy(node->surface);
381 _queue_node_delete(node);
385 _queue_init(queue *queue)
387 LIST_INITHEAD(&queue->head);
393 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
396 TBM_RETURN_IF_FAIL(cb != NULL);
398 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
400 TBM_RETURN_IF_FAIL(item != NULL);
402 LIST_INITHEAD(&item->link);
406 LIST_ADDTAIL(&item->link, list);
410 _notify_remove(struct list_head *list,
411 tbm_surface_queue_notify_cb cb, void *data)
413 queue_notify *item = NULL, *tmp;
415 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
416 if (item->cb == cb && item->data == data) {
417 LIST_DEL(&item->link);
423 TBM_LOG_E("Cannot find notifiy\n");
427 _notify_remove_all(struct list_head *list)
429 queue_notify *item = NULL, *tmp;
431 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
432 LIST_DEL(&item->link);
438 _notify_emit(tbm_surface_queue_h surface_queue,
439 struct list_head *list)
441 queue_notify *item = NULL, *tmp;;
444 The item->cb is the outside function of the libtbm.
445 The tbm user may/can remove the item of the list,
446 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
448 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
449 item->cb(surface_queue, item->data);
453 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
456 TBM_RETURN_IF_FAIL(cb != NULL);
458 queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
460 TBM_RETURN_IF_FAIL(item != NULL);
462 LIST_INITHEAD(&item->link);
466 LIST_ADDTAIL(&item->link, list);
470 _trace_remove(struct list_head *list,
471 tbm_surface_queue_trace_cb cb, void *data)
473 queue_trace *item = NULL, *tmp;
475 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
476 if (item->cb == cb && item->data == data) {
477 LIST_DEL(&item->link);
483 TBM_LOG_E("Cannot find notifiy\n");
487 _trace_remove_all(struct list_head *list)
489 queue_trace *item = NULL, *tmp;
491 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
492 LIST_DEL(&item->link);
498 _trace_emit(tbm_surface_queue_h surface_queue,
499 struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
501 queue_trace *item = NULL, *tmp;;
504 The item->cb is the outside function of the libtbm.
505 The tbm user may/can remove the item of the list,
506 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
508 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
509 item->cb(surface_queue, surface, trace, item->data);
513 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
515 queue_node *node = NULL;
518 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
519 if (node->type == type)
527 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
528 tbm_surface_h surface)
532 node = _queue_node_create();
533 TBM_RETURN_IF_FAIL(node != NULL);
535 tbm_surface_internal_ref(surface);
536 node->surface = surface;
538 LIST_ADDTAIL(&node->link, &surface_queue->list);
539 surface_queue->num_attached++;
540 _queue_node_push_back(&surface_queue->free_queue, node);
544 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
545 tbm_surface_h surface)
550 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
552 _queue_delete_node(surface_queue, node);
553 surface_queue->num_attached--;
558 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
559 queue_node *node, int push_back)
562 _queue_node_push_back(&surface_queue->dirty_queue, node);
564 _queue_node_push_front(&surface_queue->dirty_queue, node);
568 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
572 node = _queue_node_pop_front(&surface_queue->free_queue);
578 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
582 if (_queue_is_empty(&surface_queue->dirty_queue))
585 node = _queue_node_pop_front(&surface_queue->dirty_queue);
591 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
592 queue_node *node, int push_back)
595 _queue_node_push_back(&surface_queue->free_queue, node);
597 _queue_node_push_front(&surface_queue->free_queue, node);
601 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
603 int width, int height, int format,
604 const tbm_surface_queue_interface *impl, void *data)
606 TBM_RETURN_IF_FAIL(surface_queue != NULL);
607 TBM_RETURN_IF_FAIL(impl != NULL);
609 if (!g_surf_queue_bufmgr)
610 _init_tbm_surf_queue_bufmgr();
612 pthread_mutex_init(&surface_queue->lock, NULL);
613 pthread_cond_init(&surface_queue->free_cond, NULL);
614 pthread_cond_init(&surface_queue->dirty_cond, NULL);
616 surface_queue->queue_size = queue_size;
617 surface_queue->width = width;
618 surface_queue->height = height;
619 surface_queue->format = format;
620 surface_queue->impl = impl;
621 surface_queue->impl_data = data;
622 surface_queue->modes = TBM_SURFACE_QUEUE_MODE_NONE;
624 _queue_init(&surface_queue->free_queue);
625 _queue_init(&surface_queue->dirty_queue);
626 LIST_INITHEAD(&surface_queue->list);
628 LIST_INITHEAD(&surface_queue->destory_noti);
629 LIST_INITHEAD(&surface_queue->dequeuable_noti);
630 LIST_INITHEAD(&surface_queue->dequeue_noti);
631 LIST_INITHEAD(&surface_queue->can_dequeue_noti);
632 LIST_INITHEAD(&surface_queue->acquirable_noti);
633 LIST_INITHEAD(&surface_queue->reset_noti);
634 LIST_INITHEAD(&surface_queue->trace_noti);
636 if (surface_queue->impl && surface_queue->impl->init)
637 surface_queue->impl->init(surface_queue);
639 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
642 tbm_surface_queue_error_e
643 tbm_surface_queue_add_destroy_cb(
644 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
647 _tbm_surf_queue_mutex_lock();
649 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
650 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
652 pthread_mutex_lock(&surface_queue->lock);
654 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
656 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
658 pthread_mutex_unlock(&surface_queue->lock);
660 _tbm_surf_queue_mutex_unlock();
662 return TBM_SURFACE_QUEUE_ERROR_NONE;
665 tbm_surface_queue_error_e
666 tbm_surface_queue_remove_destroy_cb(
667 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
670 _tbm_surf_queue_mutex_lock();
672 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
673 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
675 pthread_mutex_lock(&surface_queue->lock);
677 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
679 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
681 pthread_mutex_unlock(&surface_queue->lock);
683 _tbm_surf_queue_mutex_unlock();
685 return TBM_SURFACE_QUEUE_ERROR_NONE;
688 tbm_surface_queue_error_e
689 tbm_surface_queue_add_dequeuable_cb(
690 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
693 _tbm_surf_queue_mutex_lock();
695 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
696 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
698 pthread_mutex_lock(&surface_queue->lock);
700 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
702 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
704 pthread_mutex_unlock(&surface_queue->lock);
706 _tbm_surf_queue_mutex_unlock();
708 return TBM_SURFACE_QUEUE_ERROR_NONE;
711 tbm_surface_queue_error_e
712 tbm_surface_queue_remove_dequeuable_cb(
713 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
716 _tbm_surf_queue_mutex_lock();
718 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
719 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
721 pthread_mutex_lock(&surface_queue->lock);
723 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
725 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
727 pthread_mutex_unlock(&surface_queue->lock);
729 _tbm_surf_queue_mutex_unlock();
731 return TBM_SURFACE_QUEUE_ERROR_NONE;
734 tbm_surface_queue_error_e
735 tbm_surface_queue_add_dequeue_cb(
736 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
739 _tbm_surf_queue_mutex_lock();
741 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
742 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
744 pthread_mutex_lock(&surface_queue->lock);
746 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
748 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
750 pthread_mutex_unlock(&surface_queue->lock);
752 _tbm_surf_queue_mutex_unlock();
754 return TBM_SURFACE_QUEUE_ERROR_NONE;
757 tbm_surface_queue_error_e
758 tbm_surface_queue_remove_dequeue_cb(
759 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
762 _tbm_surf_queue_mutex_lock();
764 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
765 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
767 pthread_mutex_lock(&surface_queue->lock);
769 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
771 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
773 pthread_mutex_unlock(&surface_queue->lock);
775 _tbm_surf_queue_mutex_unlock();
777 return TBM_SURFACE_QUEUE_ERROR_NONE;
780 tbm_surface_queue_error_e
781 tbm_surface_queue_add_can_dequeue_cb(
782 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
785 _tbm_surf_queue_mutex_lock();
787 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
788 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
790 pthread_mutex_lock(&surface_queue->lock);
792 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
794 _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
796 pthread_mutex_unlock(&surface_queue->lock);
798 _tbm_surf_queue_mutex_unlock();
800 return TBM_SURFACE_QUEUE_ERROR_NONE;
803 tbm_surface_queue_error_e
804 tbm_surface_queue_remove_can_dequeue_cb(
805 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
808 _tbm_surf_queue_mutex_lock();
810 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
811 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
813 pthread_mutex_lock(&surface_queue->lock);
815 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
817 _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
819 pthread_mutex_unlock(&surface_queue->lock);
821 _tbm_surf_queue_mutex_unlock();
823 return TBM_SURFACE_QUEUE_ERROR_NONE;
826 tbm_surface_queue_error_e
827 tbm_surface_queue_add_acquirable_cb(
828 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
831 _tbm_surf_queue_mutex_lock();
833 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
834 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
836 pthread_mutex_lock(&surface_queue->lock);
838 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
840 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
842 pthread_mutex_unlock(&surface_queue->lock);
844 _tbm_surf_queue_mutex_unlock();
846 return TBM_SURFACE_QUEUE_ERROR_NONE;
849 tbm_surface_queue_error_e
850 tbm_surface_queue_remove_acquirable_cb(
851 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
854 _tbm_surf_queue_mutex_lock();
856 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
857 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
859 pthread_mutex_lock(&surface_queue->lock);
861 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
863 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
865 pthread_mutex_unlock(&surface_queue->lock);
867 _tbm_surf_queue_mutex_unlock();
869 return TBM_SURFACE_QUEUE_ERROR_NONE;
872 tbm_surface_queue_error_e
873 tbm_surface_queue_add_trace_cb(
874 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
877 _tbm_surf_queue_mutex_lock();
879 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
880 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
882 pthread_mutex_lock(&surface_queue->lock);
884 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
886 _trace_add(&surface_queue->trace_noti, trace_cb, data);
888 pthread_mutex_unlock(&surface_queue->lock);
890 _tbm_surf_queue_mutex_unlock();
892 return TBM_SURFACE_QUEUE_ERROR_NONE;
895 tbm_surface_queue_error_e
896 tbm_surface_queue_remove_trace_cb(
897 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
900 _tbm_surf_queue_mutex_lock();
902 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
903 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
905 pthread_mutex_lock(&surface_queue->lock);
907 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
909 _trace_remove(&surface_queue->trace_noti, trace_cb, data);
911 pthread_mutex_unlock(&surface_queue->lock);
913 _tbm_surf_queue_mutex_unlock();
915 return TBM_SURFACE_QUEUE_ERROR_NONE;
918 tbm_surface_queue_error_e
919 tbm_surface_queue_set_alloc_cb(
920 tbm_surface_queue_h surface_queue,
921 tbm_surface_alloc_cb alloc_cb,
922 tbm_surface_free_cb free_cb,
925 _tbm_surf_queue_mutex_lock();
927 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
928 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
930 pthread_mutex_lock(&surface_queue->lock);
932 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
934 surface_queue->alloc_cb = alloc_cb;
935 surface_queue->free_cb = free_cb;
936 surface_queue->alloc_cb_data = data;
938 pthread_mutex_unlock(&surface_queue->lock);
940 _tbm_surf_queue_mutex_unlock();
942 return TBM_SURFACE_QUEUE_ERROR_NONE;
946 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
950 _tbm_surf_queue_mutex_lock();
952 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
954 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
956 width = surface_queue->width;
958 _tbm_surf_queue_mutex_unlock();
964 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
968 _tbm_surf_queue_mutex_lock();
970 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
972 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
974 height = surface_queue->height;
976 _tbm_surf_queue_mutex_unlock();
982 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
986 _tbm_surf_queue_mutex_lock();
988 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
990 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
992 format = surface_queue->format;
994 _tbm_surf_queue_mutex_unlock();
1000 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1004 _tbm_surf_queue_mutex_lock();
1006 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1008 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1010 queue_size = surface_queue->queue_size;
1012 _tbm_surf_queue_mutex_unlock();
1017 tbm_surface_queue_error_e
1018 tbm_surface_queue_add_reset_cb(
1019 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1022 _tbm_surf_queue_mutex_lock();
1024 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1025 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1027 pthread_mutex_lock(&surface_queue->lock);
1029 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1031 _notify_add(&surface_queue->reset_noti, reset_cb, data);
1033 pthread_mutex_unlock(&surface_queue->lock);
1035 _tbm_surf_queue_mutex_unlock();
1037 return TBM_SURFACE_QUEUE_ERROR_NONE;
1040 tbm_surface_queue_error_e
1041 tbm_surface_queue_remove_reset_cb(
1042 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1045 _tbm_surf_queue_mutex_lock();
1047 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1048 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1050 pthread_mutex_lock(&surface_queue->lock);
1052 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1054 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1056 pthread_mutex_unlock(&surface_queue->lock);
1058 _tbm_surf_queue_mutex_unlock();
1060 return TBM_SURFACE_QUEUE_ERROR_NONE;
1063 tbm_surface_queue_error_e
1064 tbm_surface_queue_enqueue(tbm_surface_queue_h
1065 surface_queue, tbm_surface_h surface)
1070 _tbm_surf_queue_mutex_lock();
1072 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1073 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1074 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1075 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1078 tbm_surface_internal_dump_buffer(surface, "enqueue");
1080 pthread_mutex_lock(&surface_queue->lock);
1082 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1084 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1085 if (node == NULL || queue_type != NODE_LIST) {
1086 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1088 pthread_mutex_unlock(&surface_queue->lock);
1090 _tbm_surf_queue_mutex_unlock();
1093 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1095 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1098 if (surface_queue->impl && surface_queue->impl->enqueue)
1099 surface_queue->impl->enqueue(surface_queue, node);
1101 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1103 if (!_queue_get_node(surface_queue, DIRTY_QUEUE, surface, NULL)) {
1104 TBM_LOG_E("enqueue surface(%p) but surface isn't present in the dirty_queue\n", surface);
1105 pthread_mutex_unlock(&surface_queue->lock);
1107 _tbm_surf_queue_mutex_unlock();
1108 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1111 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1113 pthread_mutex_unlock(&surface_queue->lock);
1114 pthread_cond_signal(&surface_queue->dirty_cond);
1116 _tbm_surf_queue_mutex_unlock();
1118 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1120 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1122 return TBM_SURFACE_QUEUE_ERROR_NONE;
1125 tbm_surface_queue_error_e
1126 tbm_surface_queue_cancel_dequeue(tbm_surface_queue_h
1127 surface_queue, tbm_surface_h surface)
1132 _tbm_surf_queue_mutex_lock();
1134 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1135 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1136 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1137 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1139 pthread_mutex_lock(&surface_queue->lock);
1141 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1143 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1144 if (node == NULL || queue_type != NODE_LIST) {
1145 TBM_LOG_E("tbm_surface_queue_cancel_dequeue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1147 pthread_mutex_unlock(&surface_queue->lock);
1149 _tbm_surf_queue_mutex_unlock();
1150 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1153 if (node->delete_pending) {
1154 TBM_QUEUE_TRACE("delete pending tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1156 _queue_delete_node(surface_queue, node);
1158 pthread_mutex_unlock(&surface_queue->lock);
1160 _tbm_surf_queue_mutex_unlock();
1162 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1164 return TBM_SURFACE_QUEUE_ERROR_NONE;
1167 if (surface_queue->queue_size < surface_queue->num_attached) {
1168 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1170 if (surface_queue->impl && surface_queue->impl->need_detach)
1171 surface_queue->impl->need_detach(surface_queue, node);
1173 _tbm_surface_queue_detach(surface_queue, surface);
1175 pthread_mutex_unlock(&surface_queue->lock);
1177 _tbm_surf_queue_mutex_unlock();
1179 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1181 return TBM_SURFACE_QUEUE_ERROR_NONE;
1184 if (surface_queue->impl && surface_queue->impl->release)
1185 surface_queue->impl->release(surface_queue, node);
1187 _tbm_surface_queue_release(surface_queue, node, 1);
1189 if (_queue_is_empty(&surface_queue->free_queue)) {
1190 pthread_mutex_unlock(&surface_queue->lock);
1192 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1193 _tbm_surf_queue_mutex_unlock();
1194 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1197 node->type = QUEUE_NODE_TYPE_RELEASE;
1199 pthread_mutex_unlock(&surface_queue->lock);
1200 pthread_cond_signal(&surface_queue->free_cond);
1202 _tbm_surf_queue_mutex_unlock();
1204 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1206 return TBM_SURFACE_QUEUE_ERROR_NONE;
1209 tbm_surface_queue_error_e
1210 tbm_surface_queue_dequeue(tbm_surface_queue_h
1211 surface_queue, tbm_surface_h *surface)
1215 _tbm_surf_queue_mutex_lock();
1217 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1218 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1219 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1220 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1224 pthread_mutex_lock(&surface_queue->lock);
1226 if (_queue_is_empty(&surface_queue->free_queue)) {
1227 if (surface_queue->impl && surface_queue->impl->need_attach)
1228 surface_queue->impl->need_attach(surface_queue);
1230 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1231 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1232 pthread_mutex_unlock(&surface_queue->lock);
1233 _tbm_surf_queue_mutex_unlock();
1234 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1238 if (surface_queue->impl && surface_queue->impl->dequeue)
1239 node = surface_queue->impl->dequeue(surface_queue);
1241 node = _tbm_surface_queue_dequeue(surface_queue);
1243 if (node == NULL || node->surface == NULL) {
1244 TBM_LOG_E("_queue_node_pop_front failed\n");
1245 pthread_mutex_unlock(&surface_queue->lock);
1247 _tbm_surf_queue_mutex_unlock();
1248 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1251 node->type = QUEUE_NODE_TYPE_DEQUEUE;
1252 *surface = node->surface;
1254 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1256 pthread_mutex_unlock(&surface_queue->lock);
1258 _tbm_surf_queue_mutex_unlock();
1260 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1262 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1264 return TBM_SURFACE_QUEUE_ERROR_NONE;
1268 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1270 _tbm_surf_queue_mutex_lock();
1272 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1274 _tbm_surf_queue_mutex_unlock();
1276 _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1278 _tbm_surf_queue_mutex_lock();
1280 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1282 pthread_mutex_lock(&surface_queue->lock);
1284 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1286 if (_queue_is_empty(&surface_queue->free_queue)) {
1287 if (surface_queue->impl && surface_queue->impl->need_attach)
1288 surface_queue->impl->need_attach(surface_queue);
1290 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1291 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1292 pthread_mutex_unlock(&surface_queue->lock);
1293 _tbm_surf_queue_mutex_unlock();
1298 if (!_queue_is_empty(&surface_queue->free_queue)) {
1299 pthread_mutex_unlock(&surface_queue->lock);
1300 _tbm_surf_queue_mutex_unlock();
1304 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1305 QUEUE_NODE_TYPE_ACQUIRE)) {
1306 _tbm_surf_queue_mutex_unlock();
1307 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1308 pthread_mutex_unlock(&surface_queue->lock);
1312 pthread_mutex_unlock(&surface_queue->lock);
1313 _tbm_surf_queue_mutex_unlock();
1317 tbm_surface_queue_error_e
1318 tbm_surface_queue_release(tbm_surface_queue_h
1319 surface_queue, tbm_surface_h surface)
1324 _tbm_surf_queue_mutex_lock();
1326 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1327 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1328 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1329 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1331 pthread_mutex_lock(&surface_queue->lock);
1333 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1335 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1336 if (node == NULL || queue_type != NODE_LIST) {
1337 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1339 pthread_mutex_unlock(&surface_queue->lock);
1341 _tbm_surf_queue_mutex_unlock();
1344 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1346 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1349 if (node->delete_pending) {
1350 TBM_QUEUE_TRACE("delete pending tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1352 _queue_delete_node(surface_queue, node);
1354 pthread_mutex_unlock(&surface_queue->lock);
1356 _tbm_surf_queue_mutex_unlock();
1358 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1360 return TBM_SURFACE_QUEUE_ERROR_NONE;
1363 if (surface_queue->queue_size < surface_queue->num_attached) {
1364 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1366 if (surface_queue->impl && surface_queue->impl->need_detach)
1367 surface_queue->impl->need_detach(surface_queue, node);
1369 _tbm_surface_queue_detach(surface_queue, surface);
1371 pthread_mutex_unlock(&surface_queue->lock);
1373 _tbm_surf_queue_mutex_unlock();
1375 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1377 return TBM_SURFACE_QUEUE_ERROR_NONE;
1380 if (surface_queue->impl && surface_queue->impl->release)
1381 surface_queue->impl->release(surface_queue, node);
1383 _tbm_surface_queue_release(surface_queue, node, 1);
1385 if (!_queue_get_node(surface_queue, FREE_QUEUE, surface, NULL)) {
1386 TBM_LOG_E("release surface(%p) but surface isn't present in the free_queue\n", surface);
1387 pthread_mutex_unlock(&surface_queue->lock);
1389 _tbm_surf_queue_mutex_unlock();
1390 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1393 node->type = QUEUE_NODE_TYPE_RELEASE;
1395 pthread_mutex_unlock(&surface_queue->lock);
1396 pthread_cond_signal(&surface_queue->free_cond);
1398 _tbm_surf_queue_mutex_unlock();
1400 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1402 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1404 return TBM_SURFACE_QUEUE_ERROR_NONE;
1407 tbm_surface_queue_error_e
1408 tbm_surface_queue_cancel_acquire(tbm_surface_queue_h
1409 surface_queue, tbm_surface_h surface)
1414 _tbm_surf_queue_mutex_lock();
1416 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1417 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1418 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1419 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1421 pthread_mutex_lock(&surface_queue->lock);
1423 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1425 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1426 if (node == NULL || queue_type != NODE_LIST) {
1427 TBM_LOG_E("tbm_surface_queue_cancel_acquire::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1429 pthread_mutex_unlock(&surface_queue->lock);
1431 _tbm_surf_queue_mutex_unlock();
1432 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1435 if (surface_queue->impl && surface_queue->impl->enqueue)
1436 surface_queue->impl->enqueue(surface_queue, node);
1438 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1440 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1441 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1442 pthread_mutex_unlock(&surface_queue->lock);
1444 _tbm_surf_queue_mutex_unlock();
1445 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1448 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1450 pthread_mutex_unlock(&surface_queue->lock);
1451 pthread_cond_signal(&surface_queue->dirty_cond);
1453 _tbm_surf_queue_mutex_unlock();
1455 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_ACQUIRE);
1457 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1459 return TBM_SURFACE_QUEUE_ERROR_NONE;
1462 tbm_surface_queue_error_e
1463 tbm_surface_queue_acquire(tbm_surface_queue_h
1464 surface_queue, tbm_surface_h *surface)
1468 _tbm_surf_queue_mutex_lock();
1472 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1473 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1474 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1475 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1477 pthread_mutex_lock(&surface_queue->lock);
1479 if (surface_queue->impl && surface_queue->impl->acquire)
1480 node = surface_queue->impl->acquire(surface_queue);
1482 node = _tbm_surface_queue_acquire(surface_queue);
1484 if (node == NULL || node->surface == NULL) {
1485 TBM_LOG_E("_queue_node_pop_front failed\n");
1486 pthread_mutex_unlock(&surface_queue->lock);
1488 _tbm_surf_queue_mutex_unlock();
1489 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1492 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1494 *surface = node->surface;
1496 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1498 pthread_mutex_unlock(&surface_queue->lock);
1500 _tbm_surf_queue_mutex_unlock();
1503 tbm_surface_internal_dump_buffer(*surface, "acquire");
1505 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1507 return TBM_SURFACE_QUEUE_ERROR_NONE;
1511 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1513 _tbm_surf_queue_mutex_lock();
1515 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1517 pthread_mutex_lock(&surface_queue->lock);
1519 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1521 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1522 pthread_mutex_unlock(&surface_queue->lock);
1523 _tbm_surf_queue_mutex_unlock();
1527 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1528 QUEUE_NODE_TYPE_DEQUEUE)) {
1529 _tbm_surf_queue_mutex_unlock();
1530 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1531 pthread_mutex_unlock(&surface_queue->lock);
1535 pthread_mutex_unlock(&surface_queue->lock);
1536 _tbm_surf_queue_mutex_unlock();
1541 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1543 queue_node *node = NULL, *tmp;
1545 _tbm_surf_queue_mutex_lock();
1547 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1549 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1551 LIST_DEL(&surface_queue->item_link);
1553 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1554 _queue_delete_node(surface_queue, node);
1556 if (surface_queue->impl && surface_queue->impl->destroy)
1557 surface_queue->impl->destroy(surface_queue);
1559 _notify_emit(surface_queue, &surface_queue->destory_noti);
1561 _notify_remove_all(&surface_queue->destory_noti);
1562 _notify_remove_all(&surface_queue->dequeuable_noti);
1563 _notify_remove_all(&surface_queue->dequeue_noti);
1564 _notify_remove_all(&surface_queue->can_dequeue_noti);
1565 _notify_remove_all(&surface_queue->acquirable_noti);
1566 _notify_remove_all(&surface_queue->reset_noti);
1567 _trace_remove_all(&surface_queue->trace_noti);
1569 pthread_mutex_destroy(&surface_queue->lock);
1571 free(surface_queue);
1573 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1574 _deinit_tbm_surf_queue_bufmgr();
1576 _tbm_surf_queue_mutex_unlock();
1579 tbm_surface_queue_error_e
1580 tbm_surface_queue_reset(tbm_surface_queue_h
1581 surface_queue, int width, int height, int format)
1583 queue_node *node = NULL, *tmp;
1585 _tbm_surf_queue_mutex_lock();
1587 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1588 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1590 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1592 if (width == surface_queue->width && height == surface_queue->height &&
1593 format == surface_queue->format) {
1594 _tbm_surf_queue_mutex_unlock();
1595 return TBM_SURFACE_QUEUE_ERROR_NONE;
1598 pthread_mutex_lock(&surface_queue->lock);
1600 surface_queue->width = width;
1601 surface_queue->height = height;
1602 surface_queue->format = format;
1604 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1605 /* Destory surface and Push to free_queue */
1606 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1607 _queue_delete_node(surface_queue, node);
1609 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1610 node->delete_pending = 1;
1612 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1613 _queue_delete_node(surface_queue, node);
1615 _queue_init(&surface_queue->dirty_queue);
1616 LIST_INITHEAD(&surface_queue->list);
1620 _queue_init(&surface_queue->free_queue);
1622 surface_queue->num_attached = 0;
1624 if (surface_queue->impl && surface_queue->impl->reset)
1625 surface_queue->impl->reset(surface_queue);
1627 pthread_mutex_unlock(&surface_queue->lock);
1628 pthread_cond_signal(&surface_queue->free_cond);
1630 _tbm_surf_queue_mutex_unlock();
1632 _notify_emit(surface_queue, &surface_queue->reset_noti);
1634 return TBM_SURFACE_QUEUE_ERROR_NONE;
1637 tbm_surface_queue_error_e
1638 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1640 _tbm_surf_queue_mutex_lock();
1642 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1643 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1645 _tbm_surf_queue_mutex_unlock();
1647 _notify_emit(surface_queue, &surface_queue->reset_noti);
1649 return TBM_SURFACE_QUEUE_ERROR_NONE;
1652 tbm_surface_queue_error_e
1653 tbm_surface_queue_set_size(tbm_surface_queue_h
1654 surface_queue, int queue_size, int flush)
1656 queue_node *node = NULL, *tmp;
1658 _tbm_surf_queue_mutex_lock();
1660 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1661 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1662 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1663 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1665 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1667 if ((surface_queue->queue_size == queue_size) && !flush) {
1668 _tbm_surf_queue_mutex_unlock();
1669 return TBM_SURFACE_QUEUE_ERROR_NONE;
1672 pthread_mutex_lock(&surface_queue->lock);
1675 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1676 /* Destory surface and Push to free_queue */
1677 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1678 _queue_delete_node(surface_queue, node);
1680 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1681 node->delete_pending = 1;
1683 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1684 _queue_delete_node(surface_queue, node);
1686 _queue_init(&surface_queue->dirty_queue);
1687 LIST_INITHEAD(&surface_queue->list);
1691 _queue_init(&surface_queue->free_queue);
1693 surface_queue->num_attached = 0;
1694 surface_queue->queue_size = queue_size;
1696 if (surface_queue->impl && surface_queue->impl->reset)
1697 surface_queue->impl->reset(surface_queue);
1699 pthread_mutex_unlock(&surface_queue->lock);
1700 pthread_cond_signal(&surface_queue->free_cond);
1702 _tbm_surf_queue_mutex_unlock();
1704 _notify_emit(surface_queue, &surface_queue->reset_noti);
1706 return TBM_SURFACE_QUEUE_ERROR_NONE;
1708 if (surface_queue->queue_size > queue_size) {
1709 int need_del = surface_queue->queue_size - queue_size;
1711 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1712 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1714 if (surface_queue->impl && surface_queue->impl->need_detach)
1715 surface_queue->impl->need_detach(surface_queue, node);
1717 _tbm_surface_queue_detach(surface_queue, node->surface);
1725 surface_queue->queue_size = queue_size;
1727 pthread_mutex_unlock(&surface_queue->lock);
1729 _tbm_surf_queue_mutex_unlock();
1731 return TBM_SURFACE_QUEUE_ERROR_NONE;
1735 tbm_surface_queue_error_e
1736 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1738 queue_node *node = NULL;
1740 _tbm_surf_queue_mutex_lock();
1742 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1743 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1745 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1747 if (surface_queue->num_attached == 0) {
1748 _tbm_surf_queue_mutex_unlock();
1749 return TBM_SURFACE_QUEUE_ERROR_NONE;
1752 pthread_mutex_lock(&surface_queue->lock);
1754 /* Destory surface in free_queue */
1755 while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1756 if (surface_queue->impl && surface_queue->impl->need_detach)
1757 surface_queue->impl->need_detach(surface_queue, node);
1759 _tbm_surface_queue_detach(surface_queue, node->surface);
1763 _queue_init(&surface_queue->free_queue);
1765 pthread_mutex_unlock(&surface_queue->lock);
1766 _tbm_surf_queue_mutex_unlock();
1768 return TBM_SURFACE_QUEUE_ERROR_NONE;
1771 tbm_surface_queue_error_e
1772 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1774 queue_node *node = NULL, *tmp;
1776 _tbm_surf_queue_mutex_lock();
1778 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1779 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1781 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1783 if (surface_queue->num_attached == 0) {
1784 _tbm_surf_queue_mutex_unlock();
1785 return TBM_SURFACE_QUEUE_ERROR_NONE;
1788 pthread_mutex_lock(&surface_queue->lock);
1790 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1791 /* Destory surface and Push to free_queue */
1792 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1793 _queue_delete_node(surface_queue, node);
1795 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1796 node->delete_pending = 1;
1798 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1799 _queue_delete_node(surface_queue, node);
1801 _queue_init(&surface_queue->dirty_queue);
1802 LIST_INITHEAD(&surface_queue->list);
1806 _queue_init(&surface_queue->free_queue);
1808 surface_queue->num_attached = 0;
1810 if (surface_queue->impl && surface_queue->impl->reset)
1811 surface_queue->impl->reset(surface_queue);
1813 pthread_mutex_unlock(&surface_queue->lock);
1814 pthread_cond_signal(&surface_queue->free_cond);
1816 _tbm_surf_queue_mutex_unlock();
1818 _notify_emit(surface_queue, &surface_queue->reset_noti);
1820 return TBM_SURFACE_QUEUE_ERROR_NONE;
1823 tbm_surface_queue_error_e
1824 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1825 tbm_surface_h *surfaces, int *num)
1827 queue_node *node = NULL;
1829 _tbm_surf_queue_mutex_lock();
1831 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1832 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1833 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1834 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1838 pthread_mutex_lock(&surface_queue->lock);
1840 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1842 surfaces[*num] = node->surface;
1847 pthread_mutex_unlock(&surface_queue->lock);
1849 _tbm_surf_queue_mutex_unlock();
1851 return TBM_SURFACE_QUEUE_ERROR_NONE;
1854 tbm_surface_queue_error_e
1855 tbm_surface_queue_get_trace_surface_num(
1856 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1858 _tbm_surf_queue_mutex_lock();
1860 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1861 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1862 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1863 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1867 pthread_mutex_lock(&surface_queue->lock);
1870 case TBM_SURFACE_QUEUE_TRACE_NONE:
1873 case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1874 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1876 case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1877 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1879 case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1880 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1882 case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1883 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1889 pthread_mutex_unlock(&surface_queue->lock);
1891 _tbm_surf_queue_mutex_unlock();
1893 return TBM_SURFACE_QUEUE_ERROR_NONE;
1898 } tbm_queue_default;
1901 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1903 free(surface_queue->impl_data);
1907 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1909 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1910 tbm_surface_h surface;
1912 if (surface_queue->queue_size == surface_queue->num_attached)
1915 if (surface_queue->alloc_cb) {
1916 pthread_mutex_unlock(&surface_queue->lock);
1917 _tbm_surf_queue_mutex_unlock();
1918 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1919 _tbm_surf_queue_mutex_lock();
1920 pthread_mutex_lock(&surface_queue->lock);
1926 tbm_surface_internal_ref(surface);
1928 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1929 surface_queue->height,
1930 surface_queue->format,
1932 TBM_RETURN_IF_FAIL(surface != NULL);
1935 _tbm_surface_queue_attach(surface_queue, surface);
1936 tbm_surface_internal_unref(surface);
1939 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1940 NULL, /*__tbm_queue_default_init*/
1941 NULL, /*__tbm_queue_default_reset*/
1942 __tbm_queue_default_destroy,
1943 __tbm_queue_default_need_attach,
1944 NULL, /*__tbm_queue_default_enqueue*/
1945 NULL, /*__tbm_queue_default_release*/
1946 NULL, /*__tbm_queue_default_dequeue*/
1947 NULL, /*__tbm_queue_default_acquire*/
1948 NULL, /*__tbm_queue_default_need_detach*/
1952 tbm_surface_queue_create(int queue_size, int width,
1953 int height, int format, int flags)
1955 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1956 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1957 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1958 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1960 _tbm_surf_queue_mutex_lock();
1962 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1963 sizeof(struct _tbm_surface_queue));
1964 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1966 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1968 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1969 sizeof(tbm_queue_default));
1971 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1972 free(surface_queue);
1973 _tbm_surf_queue_mutex_unlock();
1977 data->flags = flags;
1978 _tbm_surface_queue_init(surface_queue,
1980 width, height, format,
1981 &tbm_queue_default_impl, data);
1983 _tbm_surf_queue_mutex_unlock();
1985 return surface_queue;
1991 } tbm_queue_sequence;
1994 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1996 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1998 _queue_init(&data->dequeue_list);
2002 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
2004 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2006 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE)
2009 _queue_init(&data->dequeue_list);
2013 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
2015 free(surface_queue->impl_data);
2019 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
2021 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2022 tbm_surface_h surface;
2024 if (surface_queue->queue_size == surface_queue->num_attached)
2027 if (surface_queue->alloc_cb) {
2028 pthread_mutex_unlock(&surface_queue->lock);
2029 _tbm_surf_queue_mutex_unlock();
2030 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
2031 _tbm_surf_queue_mutex_lock();
2032 pthread_mutex_lock(&surface_queue->lock);
2038 tbm_surface_internal_ref(surface);
2040 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
2041 surface_queue->height,
2042 surface_queue->format,
2044 TBM_RETURN_IF_FAIL(surface != NULL);
2047 _tbm_surface_queue_attach(surface_queue, surface);
2048 tbm_surface_internal_unref(surface);
2052 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
2055 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2056 queue_node *first = NULL;
2058 first = container_of(data->dequeue_list.head.next, first, item_link);
2059 if (first != node) {
2063 node->priv_flags = 0;
2065 _queue_node_pop(&data->dequeue_list, node);
2066 _tbm_surface_queue_enqueue(surface_queue, node, 1);
2070 __tbm_queue_sequence_release(tbm_surface_queue_h surface_queue,
2073 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2075 if (node->priv_flags) {
2076 node->priv_flags = 0;
2077 _queue_node_pop(&data->dequeue_list, node);
2080 _tbm_surface_queue_release(surface_queue, node, 1);
2084 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
2087 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2090 node = _tbm_surface_queue_dequeue(surface_queue);
2092 _queue_node_push_back(&data->dequeue_list, node);
2093 node->priv_flags = 1;
2099 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
2100 __tbm_queue_sequence_init,
2101 __tbm_queue_sequence_reset,
2102 __tbm_queue_sequence_destroy,
2103 __tbm_queue_sequence_need_attach,
2104 __tbm_queue_sequence_enqueue,
2105 __tbm_queue_sequence_release,
2106 __tbm_queue_sequence_dequeue,
2107 NULL, /*__tbm_queue_sequence_acquire*/
2108 NULL, /*__tbm_queue_sequence_need_dettach*/
2112 tbm_surface_queue_sequence_create(int queue_size, int width,
2113 int height, int format, int flags)
2115 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
2116 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
2117 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
2118 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
2120 _tbm_surf_queue_mutex_lock();
2122 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
2123 sizeof(struct _tbm_surface_queue));
2124 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
2126 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
2128 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
2129 sizeof(tbm_queue_sequence));
2131 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
2132 free(surface_queue);
2133 _tbm_surf_queue_mutex_unlock();
2137 data->flags = flags;
2138 _tbm_surface_queue_init(surface_queue,
2140 width, height, format,
2141 &tbm_queue_sequence_impl, data);
2143 _tbm_surf_queue_mutex_unlock();
2145 return surface_queue;
2148 tbm_surface_queue_error_e
2149 tbm_surface_queue_set_modes(tbm_surface_queue_h surface_queue,
2152 _tbm_surf_queue_mutex_lock();
2154 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2155 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2157 pthread_mutex_lock(&surface_queue->lock);
2159 if (modes == TBM_SURFACE_QUEUE_MODE_NONE)
2160 modes = TBM_SURFACE_QUEUE_MODE_NONE;
2162 surface_queue->modes |= modes;
2164 pthread_mutex_unlock(&surface_queue->lock);
2166 _tbm_surf_queue_mutex_unlock();
2168 return TBM_SURFACE_QUEUE_ERROR_NONE;