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;
109 typedef struct _tbm_surface_queue_interface {
110 void (*init)(tbm_surface_queue_h queue);
111 void (*reset)(tbm_surface_queue_h queue);
112 void (*destroy)(tbm_surface_queue_h queue);
113 void (*need_attach)(tbm_surface_queue_h queue);
115 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
116 void (*release)(tbm_surface_queue_h queue, queue_node *node);
117 queue_node *(*dequeue)(tbm_surface_queue_h queue);
118 queue_node *(*acquire)(tbm_surface_queue_h queue);
119 void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
120 } tbm_surface_queue_interface;
122 struct _tbm_surface_queue {
131 struct list_head list;
133 struct list_head destory_noti;
134 struct list_head dequeuable_noti;
135 struct list_head dequeue_noti;
136 struct list_head acquirable_noti;
137 struct list_head reset_noti;
139 pthread_mutex_t lock;
140 pthread_cond_t free_cond;
141 pthread_cond_t dirty_cond;
143 const tbm_surface_queue_interface *impl;
146 //For external buffer allocation
147 tbm_surface_alloc_cb alloc_cb;
148 tbm_surface_free_cb free_cb;
151 struct list_head item_link; /* link of surface queue */
154 /* LCOV_EXCL_START */
157 _tbm_surf_queue_mutex_init(void)
159 static bool tbm_surf_queue_mutex_init = false;
161 if (tbm_surf_queue_mutex_init)
164 if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
165 TBM_LOG_E("fail: tbm_surf_queue mutex init\n");
169 tbm_surf_queue_mutex_init = true;
175 _tbm_surf_queue_mutex_lock(void)
177 if (!_tbm_surf_queue_mutex_init())
180 pthread_mutex_lock(&tbm_surf_queue_lock);
184 _tbm_surf_queue_mutex_unlock(void)
186 pthread_mutex_unlock(&tbm_surf_queue_lock);
190 _init_tbm_surf_queue_bufmgr(void)
192 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
196 _deinit_tbm_surf_queue_bufmgr(void)
198 if (!g_surf_queue_bufmgr)
201 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
202 g_surf_queue_bufmgr = NULL;
206 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
208 tbm_surface_queue_h old_data = NULL;
210 if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
211 TBM_TRACE("error: surface_queue is NULL or not initialized\n");
215 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
216 TBM_TRACE("error: surf_queue_list is empty\n");
220 LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
222 if (old_data == surface_queue) {
223 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
228 TBM_TRACE("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
233 _queue_node_create(void)
235 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
237 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
243 _queue_node_delete(queue_node *node)
245 LIST_DEL(&node->item_link);
246 LIST_DEL(&node->link);
251 _queue_is_empty(queue *queue)
253 if (LIST_IS_EMPTY(&queue->head))
260 _queue_node_push_back(queue *queue, queue_node *node)
262 LIST_ADDTAIL(&node->item_link, &queue->head);
267 _queue_node_push_front(queue *queue, queue_node *node)
269 LIST_ADD(&node->item_link, &queue->head);
274 _queue_node_pop_front(queue *queue)
278 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
280 LIST_DEL(&node->item_link);
287 _queue_node_pop(queue *queue, queue_node *node)
289 LIST_DEL(&node->item_link);
296 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
297 tbm_surface_h surface, int *out_type)
299 queue_node *node = NULL;
302 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
306 if (type & FREE_QUEUE) {
307 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
309 if (node->surface == surface) {
311 *out_type = FREE_QUEUE;
318 if (type & DIRTY_QUEUE) {
319 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
321 if (node->surface == surface) {
323 *out_type = DIRTY_QUEUE;
330 if (type & NODE_LIST) {
331 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
332 if (node->surface == surface) {
334 *out_type = NODE_LIST;
345 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
348 if (surface_queue->free_cb) {
349 surface_queue->free_cb(surface_queue,
350 surface_queue->alloc_cb_data,
354 tbm_surface_destroy(node->surface);
357 _queue_node_delete(node);
361 _queue_init(queue *queue)
363 LIST_INITHEAD(&queue->head);
369 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
372 TBM_RETURN_IF_FAIL(cb != NULL);
374 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
376 TBM_RETURN_IF_FAIL(item != NULL);
378 LIST_INITHEAD(&item->link);
382 LIST_ADDTAIL(&item->link, list);
386 _notify_remove(struct list_head *list,
387 tbm_surface_queue_notify_cb cb, void *data)
389 queue_notify *item = NULL, *tmp;
391 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
392 if (item->cb == cb && item->data == data) {
393 LIST_DEL(&item->link);
399 TBM_LOG_E("Cannot find notifiy\n");
403 _notify_remove_all(struct list_head *list)
405 queue_notify *item = NULL, *tmp;
407 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
408 LIST_DEL(&item->link);
414 _notify_emit(tbm_surface_queue_h surface_queue,
415 struct list_head *list)
417 queue_notify *item = NULL, *tmp;;
420 The item->cb is the outside function of the libtbm.
421 The tbm user may/can remove the item of the list,
422 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
424 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
425 item->cb(surface_queue, item->data);
429 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
431 queue_node *node = NULL;
434 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
435 if (node->type == type)
443 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
444 tbm_surface_h surface)
448 node = _queue_node_create();
449 TBM_RETURN_IF_FAIL(node != NULL);
451 tbm_surface_internal_ref(surface);
452 node->surface = surface;
454 LIST_ADDTAIL(&node->link, &surface_queue->list);
455 surface_queue->num_attached++;
456 _queue_node_push_back(&surface_queue->free_queue, node);
460 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
461 tbm_surface_h surface)
466 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
468 _queue_delete_node(surface_queue, node);
469 surface_queue->num_attached--;
474 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
475 queue_node *node, int push_back)
478 _queue_node_push_back(&surface_queue->dirty_queue, node);
480 _queue_node_push_front(&surface_queue->dirty_queue, node);
484 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
488 if (_queue_is_empty(&surface_queue->free_queue)) {
489 if (surface_queue->impl && surface_queue->impl->need_attach)
490 surface_queue->impl->need_attach(surface_queue);
492 if (_queue_is_empty(&surface_queue->free_queue))
496 node = _queue_node_pop_front(&surface_queue->free_queue);
502 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
506 if (_queue_is_empty(&surface_queue->dirty_queue))
509 node = _queue_node_pop_front(&surface_queue->dirty_queue);
515 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
516 queue_node *node, int push_back)
519 _queue_node_push_back(&surface_queue->free_queue, node);
521 _queue_node_push_front(&surface_queue->free_queue, node);
525 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
527 int width, int height, int format,
528 const tbm_surface_queue_interface *impl, void *data)
530 TBM_RETURN_IF_FAIL(surface_queue != NULL);
531 TBM_RETURN_IF_FAIL(impl != NULL);
533 if (!g_surf_queue_bufmgr)
534 _init_tbm_surf_queue_bufmgr();
536 pthread_mutex_init(&surface_queue->lock, NULL);
537 pthread_cond_init(&surface_queue->free_cond, NULL);
538 pthread_cond_init(&surface_queue->dirty_cond, NULL);
540 surface_queue->queue_size = queue_size;
541 surface_queue->width = width;
542 surface_queue->height = height;
543 surface_queue->format = format;
544 surface_queue->impl = impl;
545 surface_queue->impl_data = data;
547 _queue_init(&surface_queue->free_queue);
548 _queue_init(&surface_queue->dirty_queue);
549 LIST_INITHEAD(&surface_queue->list);
551 LIST_INITHEAD(&surface_queue->destory_noti);
552 LIST_INITHEAD(&surface_queue->dequeuable_noti);
553 LIST_INITHEAD(&surface_queue->dequeue_noti);
554 LIST_INITHEAD(&surface_queue->acquirable_noti);
555 LIST_INITHEAD(&surface_queue->reset_noti);
557 if (surface_queue->impl && surface_queue->impl->init)
558 surface_queue->impl->init(surface_queue);
560 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
563 tbm_surface_queue_error_e
564 tbm_surface_queue_add_destroy_cb(
565 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
568 _tbm_surf_queue_mutex_lock();
570 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
571 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
573 pthread_mutex_lock(&surface_queue->lock);
575 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
577 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
579 pthread_mutex_unlock(&surface_queue->lock);
581 _tbm_surf_queue_mutex_unlock();
583 return TBM_SURFACE_QUEUE_ERROR_NONE;
586 tbm_surface_queue_error_e
587 tbm_surface_queue_remove_destroy_cb(
588 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
591 _tbm_surf_queue_mutex_lock();
593 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
594 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
596 pthread_mutex_lock(&surface_queue->lock);
598 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
600 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
602 pthread_mutex_unlock(&surface_queue->lock);
604 _tbm_surf_queue_mutex_unlock();
606 return TBM_SURFACE_QUEUE_ERROR_NONE;
609 tbm_surface_queue_error_e
610 tbm_surface_queue_add_dequeuable_cb(
611 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
614 _tbm_surf_queue_mutex_lock();
616 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
617 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
619 pthread_mutex_lock(&surface_queue->lock);
621 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
623 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
625 pthread_mutex_unlock(&surface_queue->lock);
627 _tbm_surf_queue_mutex_unlock();
629 return TBM_SURFACE_QUEUE_ERROR_NONE;
632 tbm_surface_queue_error_e
633 tbm_surface_queue_remove_dequeuable_cb(
634 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
637 _tbm_surf_queue_mutex_lock();
639 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
640 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
642 pthread_mutex_lock(&surface_queue->lock);
644 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
646 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
648 pthread_mutex_unlock(&surface_queue->lock);
650 _tbm_surf_queue_mutex_unlock();
652 return TBM_SURFACE_QUEUE_ERROR_NONE;
655 tbm_surface_queue_error_e
656 tbm_surface_queue_add_dequeue_cb(
657 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
660 _tbm_surf_queue_mutex_lock();
662 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
663 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
665 pthread_mutex_lock(&surface_queue->lock);
667 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
669 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
671 pthread_mutex_unlock(&surface_queue->lock);
673 _tbm_surf_queue_mutex_unlock();
675 return TBM_SURFACE_QUEUE_ERROR_NONE;
678 tbm_surface_queue_error_e
679 tbm_surface_queue_remove_dequeue_cb(
680 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
683 _tbm_surf_queue_mutex_lock();
685 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
686 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
688 pthread_mutex_lock(&surface_queue->lock);
690 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
692 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
694 pthread_mutex_unlock(&surface_queue->lock);
696 _tbm_surf_queue_mutex_unlock();
698 return TBM_SURFACE_QUEUE_ERROR_NONE;
701 tbm_surface_queue_error_e
702 tbm_surface_queue_add_acquirable_cb(
703 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
706 _tbm_surf_queue_mutex_lock();
708 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
709 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
711 pthread_mutex_lock(&surface_queue->lock);
713 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
715 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
717 pthread_mutex_unlock(&surface_queue->lock);
719 _tbm_surf_queue_mutex_unlock();
721 return TBM_SURFACE_QUEUE_ERROR_NONE;
724 tbm_surface_queue_error_e
725 tbm_surface_queue_remove_acquirable_cb(
726 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
729 _tbm_surf_queue_mutex_lock();
731 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
732 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
734 pthread_mutex_lock(&surface_queue->lock);
736 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
738 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
740 pthread_mutex_unlock(&surface_queue->lock);
742 _tbm_surf_queue_mutex_unlock();
744 return TBM_SURFACE_QUEUE_ERROR_NONE;
747 tbm_surface_queue_error_e
748 tbm_surface_queue_set_alloc_cb(
749 tbm_surface_queue_h surface_queue,
750 tbm_surface_alloc_cb alloc_cb,
751 tbm_surface_free_cb free_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 surface_queue->alloc_cb = alloc_cb;
764 surface_queue->free_cb = free_cb;
765 surface_queue->alloc_cb_data = data;
767 pthread_mutex_unlock(&surface_queue->lock);
769 _tbm_surf_queue_mutex_unlock();
771 return TBM_SURFACE_QUEUE_ERROR_NONE;
775 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
779 _tbm_surf_queue_mutex_lock();
781 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
783 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
785 width = surface_queue->width;
787 _tbm_surf_queue_mutex_unlock();
793 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
797 _tbm_surf_queue_mutex_lock();
799 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
801 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
803 height = surface_queue->height;
805 _tbm_surf_queue_mutex_unlock();
811 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
815 _tbm_surf_queue_mutex_lock();
817 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
819 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
821 format = surface_queue->format;
823 _tbm_surf_queue_mutex_unlock();
829 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
833 _tbm_surf_queue_mutex_lock();
835 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
837 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
839 queue_size = surface_queue->queue_size;
841 _tbm_surf_queue_mutex_unlock();
846 tbm_surface_queue_error_e
847 tbm_surface_queue_add_reset_cb(
848 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
851 _tbm_surf_queue_mutex_lock();
853 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
854 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
856 pthread_mutex_lock(&surface_queue->lock);
858 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
860 _notify_add(&surface_queue->reset_noti, reset_cb, data);
862 pthread_mutex_unlock(&surface_queue->lock);
864 _tbm_surf_queue_mutex_unlock();
866 return TBM_SURFACE_QUEUE_ERROR_NONE;
869 tbm_surface_queue_error_e
870 tbm_surface_queue_remove_reset_cb(
871 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
874 _tbm_surf_queue_mutex_lock();
876 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
877 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
879 pthread_mutex_lock(&surface_queue->lock);
881 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
883 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
885 pthread_mutex_unlock(&surface_queue->lock);
887 _tbm_surf_queue_mutex_unlock();
889 return TBM_SURFACE_QUEUE_ERROR_NONE;
892 tbm_surface_queue_error_e
893 tbm_surface_queue_enqueue(tbm_surface_queue_h
894 surface_queue, tbm_surface_h surface)
899 _tbm_surf_queue_mutex_lock();
901 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
902 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
903 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
904 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
907 tbm_surface_internal_dump_buffer(surface, "enqueue");
909 pthread_mutex_lock(&surface_queue->lock);
911 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
913 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
914 if (node == NULL || queue_type != NODE_LIST) {
915 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
917 pthread_mutex_unlock(&surface_queue->lock);
919 _tbm_surf_queue_mutex_unlock();
920 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
923 if (surface_queue->impl && surface_queue->impl->enqueue)
924 surface_queue->impl->enqueue(surface_queue, node);
926 _tbm_surface_queue_enqueue(surface_queue, node, 1);
928 if (_queue_is_empty(&surface_queue->dirty_queue)) {
929 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
930 pthread_mutex_unlock(&surface_queue->lock);
932 _tbm_surf_queue_mutex_unlock();
933 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
936 node->type = QUEUE_NODE_TYPE_ENQUEUE;
938 pthread_mutex_unlock(&surface_queue->lock);
939 pthread_cond_signal(&surface_queue->dirty_cond);
941 _tbm_surf_queue_mutex_unlock();
943 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
945 return TBM_SURFACE_QUEUE_ERROR_NONE;
948 tbm_surface_queue_error_e
949 tbm_surface_queue_dequeue(tbm_surface_queue_h
950 surface_queue, tbm_surface_h *surface)
954 _tbm_surf_queue_mutex_lock();
958 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
959 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
960 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
961 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
963 pthread_mutex_lock(&surface_queue->lock);
965 if (surface_queue->impl && surface_queue->impl->dequeue)
966 node = surface_queue->impl->dequeue(surface_queue);
968 node = _tbm_surface_queue_dequeue(surface_queue);
970 if (node == NULL || node->surface == NULL) {
971 TBM_LOG_E("_queue_node_pop_front failed\n");
972 pthread_mutex_unlock(&surface_queue->lock);
974 _tbm_surf_queue_mutex_unlock();
975 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
978 node->type = QUEUE_NODE_TYPE_DEQUEUE;
979 *surface = node->surface;
981 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
983 pthread_mutex_unlock(&surface_queue->lock);
985 _tbm_surf_queue_mutex_unlock();
987 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
989 return TBM_SURFACE_QUEUE_ERROR_NONE;
993 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
995 _tbm_surf_queue_mutex_lock();
997 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
999 pthread_mutex_lock(&surface_queue->lock);
1001 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1003 if (_queue_is_empty(&surface_queue->free_queue)) {
1004 if (surface_queue->impl && surface_queue->impl->need_attach)
1005 surface_queue->impl->need_attach(surface_queue);
1007 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1008 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1009 _tbm_surf_queue_mutex_unlock();
1014 if (!_queue_is_empty(&surface_queue->free_queue)) {
1015 pthread_mutex_unlock(&surface_queue->lock);
1016 _tbm_surf_queue_mutex_unlock();
1020 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1021 QUEUE_NODE_TYPE_ACQUIRE)) {
1022 _tbm_surf_queue_mutex_unlock();
1023 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1024 _tbm_surf_queue_mutex_lock();
1026 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1027 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1028 pthread_mutex_unlock(&surface_queue->lock);
1029 _tbm_surf_queue_mutex_unlock();
1033 pthread_mutex_unlock(&surface_queue->lock);
1034 _tbm_surf_queue_mutex_unlock();
1038 pthread_mutex_unlock(&surface_queue->lock);
1039 _tbm_surf_queue_mutex_unlock();
1043 tbm_surface_queue_error_e
1044 tbm_surface_queue_release(tbm_surface_queue_h
1045 surface_queue, tbm_surface_h surface)
1050 _tbm_surf_queue_mutex_lock();
1052 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1053 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1054 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1055 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1057 pthread_mutex_lock(&surface_queue->lock);
1059 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1061 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1062 if (node == NULL || queue_type != NODE_LIST) {
1063 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1065 pthread_mutex_unlock(&surface_queue->lock);
1067 _tbm_surf_queue_mutex_unlock();
1068 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1071 if (surface_queue->queue_size < surface_queue->num_attached) {
1072 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1074 if (surface_queue->impl && surface_queue->impl->need_detach)
1075 surface_queue->impl->need_detach(surface_queue, node);
1077 _tbm_surface_queue_detach(surface_queue, surface);
1079 pthread_mutex_unlock(&surface_queue->lock);
1081 _tbm_surf_queue_mutex_unlock();
1082 return TBM_SURFACE_QUEUE_ERROR_NONE;
1085 if (surface_queue->impl && surface_queue->impl->release)
1086 surface_queue->impl->release(surface_queue, node);
1088 _tbm_surface_queue_release(surface_queue, node, 1);
1090 if (_queue_is_empty(&surface_queue->free_queue)) {
1091 pthread_mutex_unlock(&surface_queue->lock);
1093 _tbm_surf_queue_mutex_unlock();
1094 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1097 node->type = QUEUE_NODE_TYPE_RELEASE;
1099 pthread_mutex_unlock(&surface_queue->lock);
1100 pthread_cond_signal(&surface_queue->free_cond);
1102 _tbm_surf_queue_mutex_unlock();
1104 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1106 return TBM_SURFACE_QUEUE_ERROR_NONE;
1109 tbm_surface_queue_error_e
1110 tbm_surface_queue_acquire(tbm_surface_queue_h
1111 surface_queue, tbm_surface_h *surface)
1115 _tbm_surf_queue_mutex_lock();
1119 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1120 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1121 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1122 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1124 pthread_mutex_lock(&surface_queue->lock);
1126 if (surface_queue->impl && surface_queue->impl->acquire)
1127 node = surface_queue->impl->acquire(surface_queue);
1129 node = _tbm_surface_queue_acquire(surface_queue);
1131 if (node == NULL || node->surface == NULL) {
1132 TBM_LOG_E("_queue_node_pop_front failed\n");
1133 pthread_mutex_unlock(&surface_queue->lock);
1135 _tbm_surf_queue_mutex_unlock();
1136 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1139 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1141 *surface = node->surface;
1143 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1145 pthread_mutex_unlock(&surface_queue->lock);
1147 _tbm_surf_queue_mutex_unlock();
1150 tbm_surface_internal_dump_buffer(*surface, "acquire");
1152 return TBM_SURFACE_QUEUE_ERROR_NONE;
1156 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1158 _tbm_surf_queue_mutex_lock();
1160 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1162 pthread_mutex_lock(&surface_queue->lock);
1164 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1166 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1167 pthread_mutex_unlock(&surface_queue->lock);
1168 _tbm_surf_queue_mutex_unlock();
1172 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1173 QUEUE_NODE_TYPE_DEQUEUE)) {
1174 _tbm_surf_queue_mutex_unlock();
1175 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1176 _tbm_surf_queue_mutex_lock();
1178 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1179 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1180 pthread_mutex_unlock(&surface_queue->lock);
1181 _tbm_surf_queue_mutex_unlock();
1185 pthread_mutex_unlock(&surface_queue->lock);
1186 _tbm_surf_queue_mutex_unlock();
1190 pthread_mutex_unlock(&surface_queue->lock);
1191 _tbm_surf_queue_mutex_unlock();
1196 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1198 queue_node *node = NULL, *tmp;
1200 _tbm_surf_queue_mutex_lock();
1202 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1204 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1206 LIST_DEL(&surface_queue->item_link);
1208 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1209 _queue_delete_node(surface_queue, node);
1211 if (surface_queue->impl && surface_queue->impl->destroy)
1212 surface_queue->impl->destroy(surface_queue);
1214 _notify_emit(surface_queue, &surface_queue->destory_noti);
1216 _notify_remove_all(&surface_queue->destory_noti);
1217 _notify_remove_all(&surface_queue->dequeuable_noti);
1218 _notify_remove_all(&surface_queue->dequeue_noti);
1219 _notify_remove_all(&surface_queue->acquirable_noti);
1220 _notify_remove_all(&surface_queue->reset_noti);
1222 pthread_mutex_destroy(&surface_queue->lock);
1224 free(surface_queue);
1226 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1227 _deinit_tbm_surf_queue_bufmgr();
1229 _tbm_surf_queue_mutex_unlock();
1232 tbm_surface_queue_error_e
1233 tbm_surface_queue_reset(tbm_surface_queue_h
1234 surface_queue, int width, int height, int format)
1236 queue_node *node = NULL, *tmp;
1238 _tbm_surf_queue_mutex_lock();
1240 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1241 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1243 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1245 if (width == surface_queue->width && height == surface_queue->height &&
1246 format == surface_queue->format) {
1247 _tbm_surf_queue_mutex_unlock();
1248 return TBM_SURFACE_QUEUE_ERROR_NONE;
1251 pthread_mutex_lock(&surface_queue->lock);
1253 surface_queue->width = width;
1254 surface_queue->height = height;
1255 surface_queue->format = format;
1257 /* Destory surface and Push to free_queue */
1258 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1259 _queue_delete_node(surface_queue, node);
1262 _queue_init(&surface_queue->free_queue);
1263 _queue_init(&surface_queue->dirty_queue);
1264 LIST_INITHEAD(&surface_queue->list);
1266 surface_queue->num_attached = 0;
1268 if (surface_queue->impl && surface_queue->impl->reset)
1269 surface_queue->impl->reset(surface_queue);
1271 pthread_mutex_unlock(&surface_queue->lock);
1272 pthread_cond_signal(&surface_queue->free_cond);
1274 _tbm_surf_queue_mutex_unlock();
1276 _notify_emit(surface_queue, &surface_queue->reset_noti);
1278 return TBM_SURFACE_QUEUE_ERROR_NONE;
1281 tbm_surface_queue_error_e
1282 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1284 _tbm_surf_queue_mutex_lock();
1286 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1287 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1289 _tbm_surf_queue_mutex_unlock();
1291 _notify_emit(surface_queue, &surface_queue->reset_noti);
1293 return TBM_SURFACE_QUEUE_ERROR_NONE;
1296 tbm_surface_queue_error_e
1297 tbm_surface_queue_set_size(tbm_surface_queue_h
1298 surface_queue, int queue_size, int flush)
1300 queue_node *node = NULL, *tmp;
1302 _tbm_surf_queue_mutex_lock();
1304 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1305 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1306 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1307 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1309 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1311 if ((surface_queue->queue_size == queue_size) && !flush) {
1312 _tbm_surf_queue_mutex_unlock();
1313 return TBM_SURFACE_QUEUE_ERROR_NONE;
1316 pthread_mutex_lock(&surface_queue->lock);
1319 /* Destory surface and Push to free_queue */
1320 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1321 _queue_delete_node(surface_queue, node);
1324 _queue_init(&surface_queue->free_queue);
1325 _queue_init(&surface_queue->dirty_queue);
1326 LIST_INITHEAD(&surface_queue->list);
1328 surface_queue->num_attached = 0;
1329 surface_queue->queue_size = queue_size;
1331 if (surface_queue->impl && surface_queue->impl->reset)
1332 surface_queue->impl->reset(surface_queue);
1334 pthread_mutex_unlock(&surface_queue->lock);
1335 pthread_cond_signal(&surface_queue->free_cond);
1337 _tbm_surf_queue_mutex_unlock();
1339 _notify_emit(surface_queue, &surface_queue->reset_noti);
1341 return TBM_SURFACE_QUEUE_ERROR_NONE;
1343 if (surface_queue->queue_size > queue_size) {
1344 int need_del = surface_queue->queue_size - queue_size;
1346 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1347 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1349 if (surface_queue->impl && surface_queue->impl->need_detach)
1350 surface_queue->impl->need_detach(surface_queue, node);
1352 _tbm_surface_queue_detach(surface_queue, node->surface);
1360 surface_queue->queue_size = queue_size;
1362 pthread_mutex_unlock(&surface_queue->lock);
1364 _tbm_surf_queue_mutex_unlock();
1366 return TBM_SURFACE_QUEUE_ERROR_NONE;
1370 tbm_surface_queue_error_e
1371 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1373 queue_node *node = NULL, *tmp;
1375 _tbm_surf_queue_mutex_lock();
1377 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1378 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1380 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1382 if (surface_queue->num_attached == 0) {
1383 _tbm_surf_queue_mutex_unlock();
1384 return TBM_SURFACE_QUEUE_ERROR_NONE;
1387 pthread_mutex_lock(&surface_queue->lock);
1389 /* Destory surface and Push to free_queue */
1390 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1391 _queue_delete_node(surface_queue, node);
1394 _queue_init(&surface_queue->free_queue);
1395 _queue_init(&surface_queue->dirty_queue);
1396 LIST_INITHEAD(&surface_queue->list);
1398 surface_queue->num_attached = 0;
1400 if (surface_queue->impl && surface_queue->impl->reset)
1401 surface_queue->impl->reset(surface_queue);
1403 pthread_mutex_unlock(&surface_queue->lock);
1404 pthread_cond_signal(&surface_queue->free_cond);
1406 _tbm_surf_queue_mutex_unlock();
1408 _notify_emit(surface_queue, &surface_queue->reset_noti);
1410 return TBM_SURFACE_QUEUE_ERROR_NONE;
1413 tbm_surface_queue_error_e
1414 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1415 tbm_surface_h *surfaces, int *num)
1417 queue_node *node = NULL;
1419 _tbm_surf_queue_mutex_lock();
1423 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1424 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1425 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1426 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1428 pthread_mutex_lock(&surface_queue->lock);
1430 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1432 surfaces[*num] = node->surface;
1437 pthread_mutex_unlock(&surface_queue->lock);
1439 _tbm_surf_queue_mutex_unlock();
1441 return TBM_SURFACE_QUEUE_ERROR_NONE;
1446 } tbm_queue_default;
1449 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1451 free(surface_queue->impl_data);
1455 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1457 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1458 tbm_surface_h surface;
1460 if (surface_queue->queue_size == surface_queue->num_attached)
1463 if (surface_queue->alloc_cb) {
1464 pthread_mutex_unlock(&surface_queue->lock);
1465 _tbm_surf_queue_mutex_unlock();
1466 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1467 _tbm_surf_queue_mutex_lock();
1468 pthread_mutex_lock(&surface_queue->lock);
1473 tbm_surface_internal_ref(surface);
1475 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1476 surface_queue->height,
1477 surface_queue->format,
1479 TBM_RETURN_IF_FAIL(surface != NULL);
1482 _tbm_surface_queue_attach(surface_queue, surface);
1483 tbm_surface_internal_unref(surface);
1486 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1487 NULL, /*__tbm_queue_default_init*/
1488 NULL, /*__tbm_queue_default_reset*/
1489 __tbm_queue_default_destroy,
1490 __tbm_queue_default_need_attach,
1491 NULL, /*__tbm_queue_default_enqueue*/
1492 NULL, /*__tbm_queue_default_release*/
1493 NULL, /*__tbm_queue_default_dequeue*/
1494 NULL, /*__tbm_queue_default_acquire*/
1495 NULL, /*__tbm_queue_default_need_detach*/
1499 tbm_surface_queue_create(int queue_size, int width,
1500 int height, int format, int flags)
1502 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1503 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1504 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1505 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1507 _tbm_surf_queue_mutex_lock();
1509 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1510 sizeof(struct _tbm_surface_queue));
1511 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1513 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1515 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1516 sizeof(tbm_queue_default));
1518 free(surface_queue);
1519 _tbm_surf_queue_mutex_unlock();
1523 data->flags = flags;
1524 _tbm_surface_queue_init(surface_queue,
1526 width, height, format,
1527 &tbm_queue_default_impl, data);
1529 _tbm_surf_queue_mutex_unlock();
1531 return surface_queue;
1537 } tbm_queue_sequence;
1540 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1542 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1544 _queue_init(&data->dequeue_list);
1548 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1550 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1552 _queue_init(&data->dequeue_list);
1556 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1558 free(surface_queue->impl_data);
1562 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1564 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1565 tbm_surface_h surface;
1567 if (surface_queue->queue_size == surface_queue->num_attached)
1570 if (surface_queue->alloc_cb) {
1571 pthread_mutex_unlock(&surface_queue->lock);
1572 _tbm_surf_queue_mutex_unlock();
1573 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1574 _tbm_surf_queue_mutex_lock();
1575 pthread_mutex_lock(&surface_queue->lock);
1580 tbm_surface_internal_ref(surface);
1582 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1583 surface_queue->height,
1584 surface_queue->format,
1586 TBM_RETURN_IF_FAIL(surface != NULL);
1589 _tbm_surface_queue_attach(surface_queue, surface);
1590 tbm_surface_internal_unref(surface);
1594 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1597 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1598 queue_node *next = NULL, *tmp;
1600 node->priv_flags = 0;
1602 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1603 if (next->priv_flags)
1605 _queue_node_pop(&data->dequeue_list, next);
1606 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1611 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1614 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
1617 node = _tbm_surface_queue_dequeue(surface_queue);
1619 _queue_node_push_back(&data->dequeue_list, node);
1620 node->priv_flags = 1;
1626 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1627 __tbm_queue_sequence_init,
1628 __tbm_queue_sequence_reset,
1629 __tbm_queue_sequence_destroy,
1630 __tbm_queue_sequence_need_attach,
1631 __tbm_queue_sequence_enqueue,
1632 NULL, /*__tbm_queue_sequence_release*/
1633 __tbm_queue_sequence_dequeue,
1634 NULL, /*__tbm_queue_sequence_acquire*/
1635 NULL, /*__tbm_queue_sequence_need_dettach*/
1639 tbm_surface_queue_sequence_create(int queue_size, int width,
1640 int height, int format, int flags)
1642 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1643 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1644 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1645 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1647 _tbm_surf_queue_mutex_lock();
1649 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1650 sizeof(struct _tbm_surface_queue));
1651 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1653 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1655 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1656 sizeof(tbm_queue_sequence));
1658 free(surface_queue);
1659 _tbm_surf_queue_mutex_unlock();
1663 data->flags = flags;
1664 _tbm_surface_queue_init(surface_queue,
1666 width, height, format,
1667 &tbm_queue_sequence_impl, data);
1669 _tbm_surf_queue_mutex_unlock();
1671 return surface_queue;
1673 /* LCOV_EXCL_STOP */