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: tbm_surf_queue mutex init\n");
178 tbm_surf_queue_mutex_init = true;
184 _tbm_surf_queue_mutex_lock(void)
186 if (!_tbm_surf_queue_mutex_init())
189 pthread_mutex_lock(&tbm_surf_queue_lock);
193 _tbm_surf_queue_mutex_unlock(void)
195 pthread_mutex_unlock(&tbm_surf_queue_lock);
199 _init_tbm_surf_queue_bufmgr(void)
201 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
205 _deinit_tbm_surf_queue_bufmgr(void)
207 if (!g_surf_queue_bufmgr)
210 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
211 g_surf_queue_bufmgr = NULL;
215 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
217 tbm_surface_queue_h old_data = NULL;
219 if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
220 TBM_TRACE("error: surface_queue is NULL or not initialized\n");
224 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
225 TBM_TRACE("error: surf_queue_list is empty\n");
229 LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
231 if (old_data == surface_queue) {
232 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
237 TBM_TRACE("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
242 _queue_node_create(void)
244 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
246 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
252 _queue_node_delete(queue_node *node)
254 LIST_DEL(&node->item_link);
255 LIST_DEL(&node->link);
260 _queue_is_empty(queue *queue)
262 if (LIST_IS_EMPTY(&queue->head))
269 _queue_node_push_back(queue *queue, queue_node *node)
271 LIST_ADDTAIL(&node->item_link, &queue->head);
276 _queue_node_push_front(queue *queue, queue_node *node)
278 LIST_ADD(&node->item_link, &queue->head);
283 _queue_node_pop_front(queue *queue)
287 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
289 LIST_DEL(&node->item_link);
296 _queue_node_pop(queue *queue, queue_node *node)
298 LIST_DEL(&node->item_link);
305 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
306 tbm_surface_h surface, int *out_type)
308 queue_node *node = NULL;
311 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
315 if (type & FREE_QUEUE) {
316 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
318 if (node->surface == surface) {
320 *out_type = FREE_QUEUE;
327 if (type & DIRTY_QUEUE) {
328 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
330 if (node->surface == surface) {
332 *out_type = DIRTY_QUEUE;
339 if (type & NODE_LIST) {
340 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
341 if (node->surface == surface) {
343 *out_type = NODE_LIST;
354 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
357 if (surface_queue->free_cb) {
358 surface_queue->free_cb(surface_queue,
359 surface_queue->alloc_cb_data,
363 tbm_surface_destroy(node->surface);
366 _queue_node_delete(node);
370 _queue_init(queue *queue)
372 LIST_INITHEAD(&queue->head);
378 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
381 TBM_RETURN_IF_FAIL(cb != NULL);
383 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
385 TBM_RETURN_IF_FAIL(item != NULL);
387 LIST_INITHEAD(&item->link);
391 LIST_ADDTAIL(&item->link, list);
395 _notify_remove(struct list_head *list,
396 tbm_surface_queue_notify_cb cb, void *data)
398 queue_notify *item = NULL, *tmp;
400 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
401 if (item->cb == cb && item->data == data) {
402 LIST_DEL(&item->link);
408 TBM_LOG_E("Cannot find notifiy\n");
412 _notify_remove_all(struct list_head *list)
414 queue_notify *item = NULL, *tmp;
416 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
417 LIST_DEL(&item->link);
423 _notify_emit(tbm_surface_queue_h surface_queue,
424 struct list_head *list)
426 queue_notify *item = NULL, *tmp;;
429 The item->cb is the outside function of the libtbm.
430 The tbm user may/can remove the item of the list,
431 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
433 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
434 item->cb(surface_queue, item->data);
438 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
441 TBM_RETURN_IF_FAIL(cb != NULL);
443 queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
445 TBM_RETURN_IF_FAIL(item != NULL);
447 LIST_INITHEAD(&item->link);
451 LIST_ADDTAIL(&item->link, list);
455 _trace_remove(struct list_head *list,
456 tbm_surface_queue_trace_cb cb, void *data)
458 queue_trace *item = NULL, *tmp;
460 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
461 if (item->cb == cb && item->data == data) {
462 LIST_DEL(&item->link);
468 TBM_LOG_E("Cannot find notifiy\n");
472 _trace_remove_all(struct list_head *list)
474 queue_trace *item = NULL, *tmp;
476 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
477 LIST_DEL(&item->link);
483 _trace_emit(tbm_surface_queue_h surface_queue,
484 struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
486 queue_trace *item = NULL, *tmp;;
489 The item->cb is the outside function of the libtbm.
490 The tbm user may/can remove the item of the list,
491 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
493 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
494 item->cb(surface_queue, surface, trace, item->data);
498 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
500 queue_node *node = NULL;
503 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
504 if (node->type == type)
512 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
513 tbm_surface_h surface)
517 node = _queue_node_create();
518 TBM_RETURN_IF_FAIL(node != NULL);
520 tbm_surface_internal_ref(surface);
521 node->surface = surface;
523 LIST_ADDTAIL(&node->link, &surface_queue->list);
524 surface_queue->num_attached++;
525 _queue_node_push_back(&surface_queue->free_queue, node);
529 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
530 tbm_surface_h surface)
535 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
537 _queue_delete_node(surface_queue, node);
538 surface_queue->num_attached--;
543 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
544 queue_node *node, int push_back)
547 _queue_node_push_back(&surface_queue->dirty_queue, node);
549 _queue_node_push_front(&surface_queue->dirty_queue, node);
553 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
557 if (_queue_is_empty(&surface_queue->free_queue)) {
558 if (surface_queue->impl && surface_queue->impl->need_attach)
559 surface_queue->impl->need_attach(surface_queue);
561 if (_queue_is_empty(&surface_queue->free_queue))
565 node = _queue_node_pop_front(&surface_queue->free_queue);
571 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
575 if (_queue_is_empty(&surface_queue->dirty_queue))
578 node = _queue_node_pop_front(&surface_queue->dirty_queue);
584 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
585 queue_node *node, int push_back)
588 _queue_node_push_back(&surface_queue->free_queue, node);
590 _queue_node_push_front(&surface_queue->free_queue, node);
594 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
596 int width, int height, int format,
597 const tbm_surface_queue_interface *impl, void *data)
599 TBM_RETURN_IF_FAIL(surface_queue != NULL);
600 TBM_RETURN_IF_FAIL(impl != NULL);
602 if (!g_surf_queue_bufmgr)
603 _init_tbm_surf_queue_bufmgr();
605 pthread_mutex_init(&surface_queue->lock, NULL);
606 pthread_cond_init(&surface_queue->free_cond, NULL);
607 pthread_cond_init(&surface_queue->dirty_cond, NULL);
609 surface_queue->queue_size = queue_size;
610 surface_queue->width = width;
611 surface_queue->height = height;
612 surface_queue->format = format;
613 surface_queue->impl = impl;
614 surface_queue->impl_data = data;
616 _queue_init(&surface_queue->free_queue);
617 _queue_init(&surface_queue->dirty_queue);
618 LIST_INITHEAD(&surface_queue->list);
620 LIST_INITHEAD(&surface_queue->destory_noti);
621 LIST_INITHEAD(&surface_queue->dequeuable_noti);
622 LIST_INITHEAD(&surface_queue->dequeue_noti);
623 LIST_INITHEAD(&surface_queue->can_dequeue_noti);
624 LIST_INITHEAD(&surface_queue->acquirable_noti);
625 LIST_INITHEAD(&surface_queue->reset_noti);
626 LIST_INITHEAD(&surface_queue->trace_noti);
628 if (surface_queue->impl && surface_queue->impl->init)
629 surface_queue->impl->init(surface_queue);
631 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
634 tbm_surface_queue_error_e
635 tbm_surface_queue_add_destroy_cb(
636 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
639 _tbm_surf_queue_mutex_lock();
641 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
642 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
644 pthread_mutex_lock(&surface_queue->lock);
646 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
648 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
650 pthread_mutex_unlock(&surface_queue->lock);
652 _tbm_surf_queue_mutex_unlock();
654 return TBM_SURFACE_QUEUE_ERROR_NONE;
657 tbm_surface_queue_error_e
658 tbm_surface_queue_remove_destroy_cb(
659 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
662 _tbm_surf_queue_mutex_lock();
664 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
665 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
667 pthread_mutex_lock(&surface_queue->lock);
669 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
671 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
673 pthread_mutex_unlock(&surface_queue->lock);
675 _tbm_surf_queue_mutex_unlock();
677 return TBM_SURFACE_QUEUE_ERROR_NONE;
680 tbm_surface_queue_error_e
681 tbm_surface_queue_add_dequeuable_cb(
682 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
685 _tbm_surf_queue_mutex_lock();
687 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
688 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
690 pthread_mutex_lock(&surface_queue->lock);
692 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
694 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
696 pthread_mutex_unlock(&surface_queue->lock);
698 _tbm_surf_queue_mutex_unlock();
700 return TBM_SURFACE_QUEUE_ERROR_NONE;
703 tbm_surface_queue_error_e
704 tbm_surface_queue_remove_dequeuable_cb(
705 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
708 _tbm_surf_queue_mutex_lock();
710 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
711 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
713 pthread_mutex_lock(&surface_queue->lock);
715 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
717 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
719 pthread_mutex_unlock(&surface_queue->lock);
721 _tbm_surf_queue_mutex_unlock();
723 return TBM_SURFACE_QUEUE_ERROR_NONE;
726 tbm_surface_queue_error_e
727 tbm_surface_queue_add_dequeue_cb(
728 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
731 _tbm_surf_queue_mutex_lock();
733 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
734 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
736 pthread_mutex_lock(&surface_queue->lock);
738 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
740 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
742 pthread_mutex_unlock(&surface_queue->lock);
744 _tbm_surf_queue_mutex_unlock();
746 return TBM_SURFACE_QUEUE_ERROR_NONE;
749 tbm_surface_queue_error_e
750 tbm_surface_queue_remove_dequeue_cb(
751 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
754 _tbm_surf_queue_mutex_lock();
756 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
757 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
759 pthread_mutex_lock(&surface_queue->lock);
761 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
763 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
765 pthread_mutex_unlock(&surface_queue->lock);
767 _tbm_surf_queue_mutex_unlock();
769 return TBM_SURFACE_QUEUE_ERROR_NONE;
772 tbm_surface_queue_error_e
773 tbm_surface_queue_add_can_dequeue_cb(
774 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
777 _tbm_surf_queue_mutex_lock();
779 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
780 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
782 pthread_mutex_lock(&surface_queue->lock);
784 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
786 _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
788 pthread_mutex_unlock(&surface_queue->lock);
790 _tbm_surf_queue_mutex_unlock();
792 return TBM_SURFACE_QUEUE_ERROR_NONE;
795 tbm_surface_queue_error_e
796 tbm_surface_queue_remove_can_dequeue_cb(
797 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
800 _tbm_surf_queue_mutex_lock();
802 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
803 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
805 pthread_mutex_lock(&surface_queue->lock);
807 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
809 _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
811 pthread_mutex_unlock(&surface_queue->lock);
813 _tbm_surf_queue_mutex_unlock();
815 return TBM_SURFACE_QUEUE_ERROR_NONE;
818 tbm_surface_queue_error_e
819 tbm_surface_queue_add_acquirable_cb(
820 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
823 _tbm_surf_queue_mutex_lock();
825 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
826 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
828 pthread_mutex_lock(&surface_queue->lock);
830 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
832 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
834 pthread_mutex_unlock(&surface_queue->lock);
836 _tbm_surf_queue_mutex_unlock();
838 return TBM_SURFACE_QUEUE_ERROR_NONE;
841 tbm_surface_queue_error_e
842 tbm_surface_queue_remove_acquirable_cb(
843 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
846 _tbm_surf_queue_mutex_lock();
848 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
849 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
851 pthread_mutex_lock(&surface_queue->lock);
853 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
855 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
857 pthread_mutex_unlock(&surface_queue->lock);
859 _tbm_surf_queue_mutex_unlock();
861 return TBM_SURFACE_QUEUE_ERROR_NONE;
864 tbm_surface_queue_error_e
865 tbm_surface_queue_add_trace_cb(
866 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
869 _tbm_surf_queue_mutex_lock();
871 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
872 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
874 pthread_mutex_lock(&surface_queue->lock);
876 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
878 _trace_add(&surface_queue->trace_noti, trace_cb, data);
880 pthread_mutex_unlock(&surface_queue->lock);
882 _tbm_surf_queue_mutex_unlock();
884 return TBM_SURFACE_QUEUE_ERROR_NONE;
887 tbm_surface_queue_error_e
888 tbm_surface_queue_remove_trace_cb(
889 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
892 _tbm_surf_queue_mutex_lock();
894 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
895 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
897 pthread_mutex_lock(&surface_queue->lock);
899 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
901 _trace_remove(&surface_queue->trace_noti, trace_cb, data);
903 pthread_mutex_unlock(&surface_queue->lock);
905 _tbm_surf_queue_mutex_unlock();
907 return TBM_SURFACE_QUEUE_ERROR_NONE;
910 tbm_surface_queue_error_e
911 tbm_surface_queue_set_alloc_cb(
912 tbm_surface_queue_h surface_queue,
913 tbm_surface_alloc_cb alloc_cb,
914 tbm_surface_free_cb free_cb,
917 _tbm_surf_queue_mutex_lock();
919 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
920 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
922 pthread_mutex_lock(&surface_queue->lock);
924 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
926 surface_queue->alloc_cb = alloc_cb;
927 surface_queue->free_cb = free_cb;
928 surface_queue->alloc_cb_data = data;
930 pthread_mutex_unlock(&surface_queue->lock);
932 _tbm_surf_queue_mutex_unlock();
934 return TBM_SURFACE_QUEUE_ERROR_NONE;
938 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
942 _tbm_surf_queue_mutex_lock();
944 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
946 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
948 width = surface_queue->width;
950 _tbm_surf_queue_mutex_unlock();
956 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
960 _tbm_surf_queue_mutex_lock();
962 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
964 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
966 height = surface_queue->height;
968 _tbm_surf_queue_mutex_unlock();
974 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
978 _tbm_surf_queue_mutex_lock();
980 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
982 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
984 format = surface_queue->format;
986 _tbm_surf_queue_mutex_unlock();
992 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
996 _tbm_surf_queue_mutex_lock();
998 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1000 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1002 queue_size = surface_queue->queue_size;
1004 _tbm_surf_queue_mutex_unlock();
1009 tbm_surface_queue_error_e
1010 tbm_surface_queue_add_reset_cb(
1011 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1014 _tbm_surf_queue_mutex_lock();
1016 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1017 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1019 pthread_mutex_lock(&surface_queue->lock);
1021 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1023 _notify_add(&surface_queue->reset_noti, reset_cb, data);
1025 pthread_mutex_unlock(&surface_queue->lock);
1027 _tbm_surf_queue_mutex_unlock();
1029 return TBM_SURFACE_QUEUE_ERROR_NONE;
1032 tbm_surface_queue_error_e
1033 tbm_surface_queue_remove_reset_cb(
1034 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1037 _tbm_surf_queue_mutex_lock();
1039 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1040 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1042 pthread_mutex_lock(&surface_queue->lock);
1044 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1046 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1048 pthread_mutex_unlock(&surface_queue->lock);
1050 _tbm_surf_queue_mutex_unlock();
1052 return TBM_SURFACE_QUEUE_ERROR_NONE;
1055 tbm_surface_queue_error_e
1056 tbm_surface_queue_enqueue(tbm_surface_queue_h
1057 surface_queue, tbm_surface_h surface)
1062 _tbm_surf_queue_mutex_lock();
1064 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1065 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1066 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1067 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1070 tbm_surface_internal_dump_buffer(surface, "enqueue");
1072 pthread_mutex_lock(&surface_queue->lock);
1074 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1076 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1077 if (node == NULL || queue_type != NODE_LIST) {
1078 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1080 pthread_mutex_unlock(&surface_queue->lock);
1082 _tbm_surf_queue_mutex_unlock();
1083 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1086 if (surface_queue->impl && surface_queue->impl->enqueue)
1087 surface_queue->impl->enqueue(surface_queue, node);
1089 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1091 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1092 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1093 pthread_mutex_unlock(&surface_queue->lock);
1095 _tbm_surf_queue_mutex_unlock();
1096 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1099 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1101 pthread_mutex_unlock(&surface_queue->lock);
1102 pthread_cond_signal(&surface_queue->dirty_cond);
1104 _tbm_surf_queue_mutex_unlock();
1106 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1108 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1110 return TBM_SURFACE_QUEUE_ERROR_NONE;
1113 tbm_surface_queue_error_e
1114 tbm_surface_queue_dequeue(tbm_surface_queue_h
1115 surface_queue, tbm_surface_h *surface)
1119 _tbm_surf_queue_mutex_lock();
1123 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1124 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1125 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1126 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1128 pthread_mutex_lock(&surface_queue->lock);
1130 if (surface_queue->impl && surface_queue->impl->dequeue)
1131 node = surface_queue->impl->dequeue(surface_queue);
1133 node = _tbm_surface_queue_dequeue(surface_queue);
1135 if (node == NULL || node->surface == NULL) {
1136 TBM_LOG_E("_queue_node_pop_front failed\n");
1137 pthread_mutex_unlock(&surface_queue->lock);
1139 _tbm_surf_queue_mutex_unlock();
1140 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1143 node->type = QUEUE_NODE_TYPE_DEQUEUE;
1144 *surface = node->surface;
1146 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1148 pthread_mutex_unlock(&surface_queue->lock);
1150 _tbm_surf_queue_mutex_unlock();
1152 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1154 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1156 return TBM_SURFACE_QUEUE_ERROR_NONE;
1160 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1162 _tbm_surf_queue_mutex_lock();
1164 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1166 _tbm_surf_queue_mutex_unlock();
1168 _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1170 _tbm_surf_queue_mutex_lock();
1172 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1174 pthread_mutex_lock(&surface_queue->lock);
1176 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1178 if (_queue_is_empty(&surface_queue->free_queue)) {
1179 if (surface_queue->impl && surface_queue->impl->need_attach)
1180 surface_queue->impl->need_attach(surface_queue);
1182 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1183 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1184 _tbm_surf_queue_mutex_unlock();
1189 if (!_queue_is_empty(&surface_queue->free_queue)) {
1190 pthread_mutex_unlock(&surface_queue->lock);
1191 _tbm_surf_queue_mutex_unlock();
1195 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1196 QUEUE_NODE_TYPE_ACQUIRE)) {
1197 _tbm_surf_queue_mutex_unlock();
1198 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1199 _tbm_surf_queue_mutex_lock();
1201 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1202 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1203 pthread_mutex_unlock(&surface_queue->lock);
1204 _tbm_surf_queue_mutex_unlock();
1208 pthread_mutex_unlock(&surface_queue->lock);
1209 _tbm_surf_queue_mutex_unlock();
1213 pthread_mutex_unlock(&surface_queue->lock);
1214 _tbm_surf_queue_mutex_unlock();
1218 tbm_surface_queue_error_e
1219 tbm_surface_queue_release(tbm_surface_queue_h
1220 surface_queue, tbm_surface_h surface)
1225 _tbm_surf_queue_mutex_lock();
1227 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1228 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1229 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1230 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1232 pthread_mutex_lock(&surface_queue->lock);
1234 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1236 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1237 if (node == NULL || queue_type != NODE_LIST) {
1238 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1240 pthread_mutex_unlock(&surface_queue->lock);
1242 _tbm_surf_queue_mutex_unlock();
1243 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1246 if (surface_queue->queue_size < surface_queue->num_attached) {
1247 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1249 if (surface_queue->impl && surface_queue->impl->need_detach)
1250 surface_queue->impl->need_detach(surface_queue, node);
1252 _tbm_surface_queue_detach(surface_queue, surface);
1254 pthread_mutex_unlock(&surface_queue->lock);
1256 _tbm_surf_queue_mutex_unlock();
1257 return TBM_SURFACE_QUEUE_ERROR_NONE;
1260 if (surface_queue->impl && surface_queue->impl->release)
1261 surface_queue->impl->release(surface_queue, node);
1263 _tbm_surface_queue_release(surface_queue, node, 1);
1265 if (_queue_is_empty(&surface_queue->free_queue)) {
1266 pthread_mutex_unlock(&surface_queue->lock);
1268 _tbm_surf_queue_mutex_unlock();
1269 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1272 node->type = QUEUE_NODE_TYPE_RELEASE;
1274 pthread_mutex_unlock(&surface_queue->lock);
1275 pthread_cond_signal(&surface_queue->free_cond);
1277 _tbm_surf_queue_mutex_unlock();
1279 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1281 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1283 return TBM_SURFACE_QUEUE_ERROR_NONE;
1286 tbm_surface_queue_error_e
1287 tbm_surface_queue_acquire(tbm_surface_queue_h
1288 surface_queue, tbm_surface_h *surface)
1292 _tbm_surf_queue_mutex_lock();
1296 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1297 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1298 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1299 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1301 pthread_mutex_lock(&surface_queue->lock);
1303 if (surface_queue->impl && surface_queue->impl->acquire)
1304 node = surface_queue->impl->acquire(surface_queue);
1306 node = _tbm_surface_queue_acquire(surface_queue);
1308 if (node == NULL || node->surface == NULL) {
1309 TBM_LOG_E("_queue_node_pop_front failed\n");
1310 pthread_mutex_unlock(&surface_queue->lock);
1312 _tbm_surf_queue_mutex_unlock();
1313 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1316 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1318 *surface = node->surface;
1320 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1322 pthread_mutex_unlock(&surface_queue->lock);
1324 _tbm_surf_queue_mutex_unlock();
1327 tbm_surface_internal_dump_buffer(*surface, "acquire");
1329 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1331 return TBM_SURFACE_QUEUE_ERROR_NONE;
1335 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1337 _tbm_surf_queue_mutex_lock();
1339 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1341 pthread_mutex_lock(&surface_queue->lock);
1343 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1345 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1346 pthread_mutex_unlock(&surface_queue->lock);
1347 _tbm_surf_queue_mutex_unlock();
1351 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1352 QUEUE_NODE_TYPE_DEQUEUE)) {
1353 _tbm_surf_queue_mutex_unlock();
1354 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1355 _tbm_surf_queue_mutex_lock();
1357 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1358 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1359 pthread_mutex_unlock(&surface_queue->lock);
1360 _tbm_surf_queue_mutex_unlock();
1364 pthread_mutex_unlock(&surface_queue->lock);
1365 _tbm_surf_queue_mutex_unlock();
1369 pthread_mutex_unlock(&surface_queue->lock);
1370 _tbm_surf_queue_mutex_unlock();
1375 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1377 queue_node *node = NULL, *tmp;
1379 _tbm_surf_queue_mutex_lock();
1381 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1383 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1385 LIST_DEL(&surface_queue->item_link);
1387 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1388 _queue_delete_node(surface_queue, node);
1390 if (surface_queue->impl && surface_queue->impl->destroy)
1391 surface_queue->impl->destroy(surface_queue);
1393 _notify_emit(surface_queue, &surface_queue->destory_noti);
1395 _notify_remove_all(&surface_queue->destory_noti);
1396 _notify_remove_all(&surface_queue->dequeuable_noti);
1397 _notify_remove_all(&surface_queue->dequeue_noti);
1398 _notify_remove_all(&surface_queue->can_dequeue_noti);
1399 _notify_remove_all(&surface_queue->acquirable_noti);
1400 _notify_remove_all(&surface_queue->reset_noti);
1401 _trace_remove_all(&surface_queue->trace_noti);
1403 pthread_mutex_destroy(&surface_queue->lock);
1405 free(surface_queue);
1407 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1408 _deinit_tbm_surf_queue_bufmgr();
1410 _tbm_surf_queue_mutex_unlock();
1413 tbm_surface_queue_error_e
1414 tbm_surface_queue_reset(tbm_surface_queue_h
1415 surface_queue, int width, int height, int format)
1417 queue_node *node = NULL, *tmp;
1419 _tbm_surf_queue_mutex_lock();
1421 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1422 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1424 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1426 if (width == surface_queue->width && height == surface_queue->height &&
1427 format == surface_queue->format) {
1428 _tbm_surf_queue_mutex_unlock();
1429 return TBM_SURFACE_QUEUE_ERROR_NONE;
1432 pthread_mutex_lock(&surface_queue->lock);
1434 surface_queue->width = width;
1435 surface_queue->height = height;
1436 surface_queue->format = format;
1438 /* Destory surface and Push to free_queue */
1439 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1440 _queue_delete_node(surface_queue, node);
1443 _queue_init(&surface_queue->free_queue);
1444 _queue_init(&surface_queue->dirty_queue);
1445 LIST_INITHEAD(&surface_queue->list);
1447 surface_queue->num_attached = 0;
1449 if (surface_queue->impl && surface_queue->impl->reset)
1450 surface_queue->impl->reset(surface_queue);
1452 pthread_mutex_unlock(&surface_queue->lock);
1453 pthread_cond_signal(&surface_queue->free_cond);
1455 _tbm_surf_queue_mutex_unlock();
1457 _notify_emit(surface_queue, &surface_queue->reset_noti);
1459 return TBM_SURFACE_QUEUE_ERROR_NONE;
1462 tbm_surface_queue_error_e
1463 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1465 _tbm_surf_queue_mutex_lock();
1467 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1468 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1470 _tbm_surf_queue_mutex_unlock();
1472 _notify_emit(surface_queue, &surface_queue->reset_noti);
1474 return TBM_SURFACE_QUEUE_ERROR_NONE;
1477 tbm_surface_queue_error_e
1478 tbm_surface_queue_set_size(tbm_surface_queue_h
1479 surface_queue, int queue_size, int flush)
1481 queue_node *node = NULL, *tmp;
1483 _tbm_surf_queue_mutex_lock();
1485 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1486 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1487 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1488 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1490 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1492 if ((surface_queue->queue_size == queue_size) && !flush) {
1493 _tbm_surf_queue_mutex_unlock();
1494 return TBM_SURFACE_QUEUE_ERROR_NONE;
1497 pthread_mutex_lock(&surface_queue->lock);
1500 /* Destory surface and Push to free_queue */
1501 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1502 _queue_delete_node(surface_queue, node);
1505 _queue_init(&surface_queue->free_queue);
1506 _queue_init(&surface_queue->dirty_queue);
1507 LIST_INITHEAD(&surface_queue->list);
1509 surface_queue->num_attached = 0;
1510 surface_queue->queue_size = queue_size;
1512 if (surface_queue->impl && surface_queue->impl->reset)
1513 surface_queue->impl->reset(surface_queue);
1515 pthread_mutex_unlock(&surface_queue->lock);
1516 pthread_cond_signal(&surface_queue->free_cond);
1518 _tbm_surf_queue_mutex_unlock();
1520 _notify_emit(surface_queue, &surface_queue->reset_noti);
1522 return TBM_SURFACE_QUEUE_ERROR_NONE;
1524 if (surface_queue->queue_size > queue_size) {
1525 int need_del = surface_queue->queue_size - queue_size;
1527 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1528 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1530 if (surface_queue->impl && surface_queue->impl->need_detach)
1531 surface_queue->impl->need_detach(surface_queue, node);
1533 _tbm_surface_queue_detach(surface_queue, node->surface);
1541 surface_queue->queue_size = queue_size;
1543 pthread_mutex_unlock(&surface_queue->lock);
1545 _tbm_surf_queue_mutex_unlock();
1547 return TBM_SURFACE_QUEUE_ERROR_NONE;
1551 tbm_surface_queue_error_e
1552 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1554 queue_node *node = NULL, *tmp;
1556 _tbm_surf_queue_mutex_lock();
1558 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1559 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1561 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1563 if (surface_queue->num_attached == 0) {
1564 _tbm_surf_queue_mutex_unlock();
1565 return TBM_SURFACE_QUEUE_ERROR_NONE;
1568 pthread_mutex_lock(&surface_queue->lock);
1570 /* Destory surface and Push to free_queue */
1571 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1572 _queue_delete_node(surface_queue, node);
1575 _queue_init(&surface_queue->free_queue);
1576 _queue_init(&surface_queue->dirty_queue);
1577 LIST_INITHEAD(&surface_queue->list);
1579 surface_queue->num_attached = 0;
1581 if (surface_queue->impl && surface_queue->impl->reset)
1582 surface_queue->impl->reset(surface_queue);
1584 pthread_mutex_unlock(&surface_queue->lock);
1585 pthread_cond_signal(&surface_queue->free_cond);
1587 _tbm_surf_queue_mutex_unlock();
1589 _notify_emit(surface_queue, &surface_queue->reset_noti);
1591 return TBM_SURFACE_QUEUE_ERROR_NONE;
1594 tbm_surface_queue_error_e
1595 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1596 tbm_surface_h *surfaces, int *num)
1598 queue_node *node = NULL;
1600 _tbm_surf_queue_mutex_lock();
1604 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1605 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1606 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1607 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1609 pthread_mutex_lock(&surface_queue->lock);
1611 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1613 surfaces[*num] = node->surface;
1618 pthread_mutex_unlock(&surface_queue->lock);
1620 _tbm_surf_queue_mutex_unlock();
1622 return TBM_SURFACE_QUEUE_ERROR_NONE;
1627 } tbm_queue_default;
1630 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1632 free(surface_queue->impl_data);
1636 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1638 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1639 tbm_surface_h surface;
1641 if (surface_queue->queue_size == surface_queue->num_attached)
1644 if (surface_queue->alloc_cb) {
1645 pthread_mutex_unlock(&surface_queue->lock);
1646 _tbm_surf_queue_mutex_unlock();
1647 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1648 _tbm_surf_queue_mutex_lock();
1649 pthread_mutex_lock(&surface_queue->lock);
1654 tbm_surface_internal_ref(surface);
1656 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1657 surface_queue->height,
1658 surface_queue->format,
1660 TBM_RETURN_IF_FAIL(surface != NULL);
1663 _tbm_surface_queue_attach(surface_queue, surface);
1664 tbm_surface_internal_unref(surface);
1667 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1668 NULL, /*__tbm_queue_default_init*/
1669 NULL, /*__tbm_queue_default_reset*/
1670 __tbm_queue_default_destroy,
1671 __tbm_queue_default_need_attach,
1672 NULL, /*__tbm_queue_default_enqueue*/
1673 NULL, /*__tbm_queue_default_release*/
1674 NULL, /*__tbm_queue_default_dequeue*/
1675 NULL, /*__tbm_queue_default_acquire*/
1676 NULL, /*__tbm_queue_default_need_detach*/
1680 tbm_surface_queue_create(int queue_size, int width,
1681 int height, int format, int flags)
1683 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1684 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1685 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1686 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1688 _tbm_surf_queue_mutex_lock();
1690 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1691 sizeof(struct _tbm_surface_queue));
1692 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1694 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1696 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1697 sizeof(tbm_queue_default));
1699 free(surface_queue);
1700 _tbm_surf_queue_mutex_unlock();
1704 data->flags = flags;
1705 _tbm_surface_queue_init(surface_queue,
1707 width, height, format,
1708 &tbm_queue_default_impl, data);
1710 _tbm_surf_queue_mutex_unlock();
1712 return surface_queue;
1718 } tbm_queue_sequence;
1721 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1723 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1725 _queue_init(&data->dequeue_list);
1729 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1731 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1733 _queue_init(&data->dequeue_list);
1737 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1739 free(surface_queue->impl_data);
1743 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1745 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1746 tbm_surface_h surface;
1748 if (surface_queue->queue_size == surface_queue->num_attached)
1751 if (surface_queue->alloc_cb) {
1752 pthread_mutex_unlock(&surface_queue->lock);
1753 _tbm_surf_queue_mutex_unlock();
1754 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1755 _tbm_surf_queue_mutex_lock();
1756 pthread_mutex_lock(&surface_queue->lock);
1761 tbm_surface_internal_ref(surface);
1763 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1764 surface_queue->height,
1765 surface_queue->format,
1767 TBM_RETURN_IF_FAIL(surface != NULL);
1770 _tbm_surface_queue_attach(surface_queue, surface);
1771 tbm_surface_internal_unref(surface);
1775 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1778 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1779 queue_node *next = NULL, *tmp;
1781 node->priv_flags = 0;
1783 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1784 if (next->priv_flags)
1786 _queue_node_pop(&data->dequeue_list, next);
1787 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1792 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1795 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1798 node = _tbm_surface_queue_dequeue(surface_queue);
1800 _queue_node_push_back(&data->dequeue_list, node);
1801 node->priv_flags = 1;
1807 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1808 __tbm_queue_sequence_init,
1809 __tbm_queue_sequence_reset,
1810 __tbm_queue_sequence_destroy,
1811 __tbm_queue_sequence_need_attach,
1812 __tbm_queue_sequence_enqueue,
1813 NULL, /*__tbm_queue_sequence_release*/
1814 __tbm_queue_sequence_dequeue,
1815 NULL, /*__tbm_queue_sequence_acquire*/
1816 NULL, /*__tbm_queue_sequence_need_dettach*/
1820 tbm_surface_queue_sequence_create(int queue_size, int width,
1821 int height, int format, int flags)
1823 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1824 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1825 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1826 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1828 _tbm_surf_queue_mutex_lock();
1830 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1831 sizeof(struct _tbm_surface_queue));
1832 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1834 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1836 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1837 sizeof(tbm_queue_sequence));
1839 free(surface_queue);
1840 _tbm_surf_queue_mutex_unlock();
1844 data->flags = flags;
1845 _tbm_surface_queue_init(surface_queue,
1847 width, height, format,
1848 &tbm_queue_sequence_impl, data);
1850 _tbm_surf_queue_mutex_unlock();
1852 return surface_queue;
1854 /* LCOV_EXCL_STOP */