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 **************************************************************************/
32 #include "tbm_bufmgr_int.h"
39 #define TBM_QUEUE_DEBUG 0
42 #define TBM_QUEUE_TRACE(fmt, ...) { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
44 #define TBM_QUEUE_TRACE(fmt, ...)
48 #define TBM_LOCK() TBM_LOG_D("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
49 #define TBM_UNLOCK() TBM_LOG_D("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
55 static tbm_bufmgr g_surf_queue_bufmgr;
56 static pthread_mutex_t tbm_surf_queue_lock;
57 void _tbm_surface_queue_mutex_unlock(void);
60 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
62 TBM_LOG_E("'%s' failed.\n", #cond);\
63 _tbm_surf_queue_mutex_unlock();\
68 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
70 TBM_LOG_E("'%s' failed.\n", #cond);\
71 _tbm_surf_queue_mutex_unlock();\
76 typedef enum _queue_node_type {
78 QUEUE_NODE_TYPE_DEQUEUE,
79 QUEUE_NODE_TYPE_ENQUEUE,
80 QUEUE_NODE_TYPE_ACQUIRE,
81 QUEUE_NODE_TYPE_RELEASE
85 struct list_head head;
90 tbm_surface_h surface;
92 struct list_head item_link;
93 struct list_head link;
97 unsigned int priv_flags; /*for each queue*/
101 struct list_head link;
103 tbm_surface_queue_notify_cb cb;
107 typedef struct _tbm_surface_queue_interface {
108 void (*init)(tbm_surface_queue_h queue);
109 void (*reset)(tbm_surface_queue_h queue);
110 void (*destroy)(tbm_surface_queue_h queue);
111 void (*need_attach)(tbm_surface_queue_h queue);
113 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
114 void (*release)(tbm_surface_queue_h queue, queue_node *node);
115 queue_node *(*dequeue)(tbm_surface_queue_h queue);
116 queue_node *(*acquire)(tbm_surface_queue_h queue);
117 } tbm_surface_queue_interface;
119 struct _tbm_surface_queue {
127 struct list_head list;
129 struct list_head destory_noti;
130 struct list_head dequeuable_noti;
131 struct list_head dequeue_noti;
132 struct list_head acquirable_noti;
133 struct list_head reset_noti;
135 pthread_mutex_t lock;
136 pthread_cond_t free_cond;
137 pthread_cond_t dirty_cond;
139 const tbm_surface_queue_interface *impl;
142 //For external buffer allocation
143 tbm_surface_alloc_cb alloc_cb;
144 tbm_surface_free_cb free_cb;
147 struct list_head item_link; /* link of surface queue */
150 /* LCOV_EXCL_START */
153 _tbm_surf_queue_mutex_init(void)
155 static bool tbm_surf_queue_mutex_init = false;
157 if (tbm_surf_queue_mutex_init)
160 if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
161 TBM_LOG_E("fail: tbm_surf_queue mutex init\n");
165 tbm_surf_queue_mutex_init = true;
171 _tbm_surf_queue_mutex_lock(void)
173 if (!_tbm_surf_queue_mutex_init())
176 pthread_mutex_lock(&tbm_surf_queue_lock);
180 _tbm_surf_queue_mutex_unlock(void)
182 pthread_mutex_unlock(&tbm_surf_queue_lock);
186 _init_tbm_surf_queue_bufmgr(void)
188 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
192 _deinit_tbm_surf_queue_bufmgr(void)
194 if (!g_surf_queue_bufmgr)
197 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
198 g_surf_queue_bufmgr = NULL;
202 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
204 tbm_surface_queue_h old_data = NULL, tmp = NULL;
206 if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
207 TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue);
211 if (!LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
212 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surf_queue_bufmgr->surf_queue_list, item_link) {
213 if (old_data == surface_queue) {
214 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
219 TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue);
224 _queue_node_create(void)
226 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
228 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
234 _queue_node_delete(queue_node *node)
236 LIST_DEL(&node->item_link);
237 LIST_DEL(&node->link);
242 _queue_is_empty(queue *queue)
244 if (LIST_IS_EMPTY(&queue->head))
251 _queue_node_push_back(queue *queue, queue_node *node)
253 LIST_ADDTAIL(&node->item_link, &queue->head);
258 _queue_node_push_front(queue *queue, queue_node *node)
260 LIST_ADD(&node->item_link, &queue->head);
265 _queue_node_pop_front(queue *queue)
267 queue_node *node = NULL;
269 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
271 LIST_DEL(&node->item_link);
278 _queue_node_pop(queue *queue, queue_node *node)
280 LIST_DEL(&node->item_link);
287 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
288 tbm_surface_h surface, int *out_type)
290 queue_node *node = NULL;
291 queue_node *tmp = NULL;
294 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
298 if (type & FREE_QUEUE) {
299 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
301 if (node->surface == surface) {
303 *out_type = FREE_QUEUE;
310 if (type & DIRTY_QUEUE) {
311 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
313 if (node->surface == surface) {
315 *out_type = DIRTY_QUEUE;
322 if (type & NODE_LIST) {
323 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
324 if (node->surface == surface) {
326 *out_type = NODE_LIST;
337 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
340 if (surface_queue->free_cb) {
341 surface_queue->free_cb(surface_queue,
342 surface_queue->alloc_cb_data,
346 tbm_surface_destroy(node->surface);
349 _queue_node_delete(node);
353 _queue_init(queue *queue)
355 LIST_INITHEAD(&queue->head);
361 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
364 TBM_RETURN_IF_FAIL(cb != NULL);
366 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
368 TBM_RETURN_IF_FAIL(item != NULL);
370 LIST_INITHEAD(&item->link);
374 LIST_ADDTAIL(&item->link, list);
378 _notify_remove(struct list_head *list,
379 tbm_surface_queue_notify_cb cb, void *data)
381 queue_notify *item = NULL, *tmp = NULL;
383 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
384 if (item->cb == cb && item->data == data) {
385 LIST_DEL(&item->link);
391 TBM_LOG_E("Cannot find notifiy\n");
395 _notify_remove_all(struct list_head *list)
397 queue_notify *item = NULL, *tmp = NULL;
399 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
400 LIST_DEL(&item->link);
406 _notify_emit(tbm_surface_queue_h surface_queue,
407 struct list_head *list)
409 queue_notify *item = NULL, *tmp = NULL;
411 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
412 item->cb(surface_queue, item->data);
417 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
419 queue_node *node = NULL;
420 queue_node *tmp = NULL;
423 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
424 if (node->type == type)
432 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
433 tbm_surface_h surface)
435 queue_node *node = NULL;
437 node = _queue_node_create();
438 TBM_RETURN_IF_FAIL(node != NULL);
440 tbm_surface_internal_ref(surface);
441 node->surface = surface;
443 LIST_ADDTAIL(&node->link, &surface_queue->list);
444 _queue_node_push_back(&surface_queue->free_queue, node);
448 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
449 tbm_surface_h surface)
451 queue_node *node = NULL;
454 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
456 _queue_delete_node(surface_queue, node);
460 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
461 queue_node *node, int push_back)
464 _queue_node_push_back(&surface_queue->dirty_queue, node);
466 _queue_node_push_front(&surface_queue->dirty_queue, node);
470 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
472 queue_node *node = NULL;
474 if (_queue_is_empty(&surface_queue->free_queue)) {
475 if (surface_queue->impl && surface_queue->impl->need_attach)
476 surface_queue->impl->need_attach(surface_queue);
478 if (_queue_is_empty(&surface_queue->free_queue))
482 node = _queue_node_pop_front(&surface_queue->free_queue);
488 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
490 queue_node *node = NULL;
492 if (_queue_is_empty(&surface_queue->dirty_queue))
495 node = _queue_node_pop_front(&surface_queue->dirty_queue);
501 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
502 queue_node *node, int push_back)
505 _queue_node_push_back(&surface_queue->free_queue, node);
507 _queue_node_push_front(&surface_queue->free_queue, node);
511 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
513 int width, int height, int format,
514 const tbm_surface_queue_interface *impl, void *data)
516 TBM_RETURN_IF_FAIL(surface_queue != NULL);
517 TBM_RETURN_IF_FAIL(impl != NULL);
519 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
521 if (!g_surf_queue_bufmgr)
522 _init_tbm_surf_queue_bufmgr();
524 pthread_mutex_init(&surface_queue->lock, NULL);
525 pthread_cond_init(&surface_queue->free_cond, NULL);
526 pthread_cond_init(&surface_queue->dirty_cond, NULL);
528 surface_queue->queue_size = queue_size;
529 surface_queue->width = width;
530 surface_queue->height = height;
531 surface_queue->format = format;
532 surface_queue->impl = impl;
533 surface_queue->impl_data = data;
535 _queue_init(&surface_queue->free_queue);
536 _queue_init(&surface_queue->dirty_queue);
537 LIST_INITHEAD(&surface_queue->list);
539 LIST_INITHEAD(&surface_queue->destory_noti);
540 LIST_INITHEAD(&surface_queue->acquirable_noti);
541 LIST_INITHEAD(&surface_queue->dequeuable_noti);
542 LIST_INITHEAD(&surface_queue->dequeue_noti);
543 LIST_INITHEAD(&surface_queue->reset_noti);
545 if (surface_queue->impl && surface_queue->impl->init)
546 surface_queue->impl->init(surface_queue);
548 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
551 tbm_surface_queue_error_e
552 tbm_surface_queue_add_destroy_cb(
553 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
556 _tbm_surf_queue_mutex_lock();
558 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
559 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
561 pthread_mutex_lock(&surface_queue->lock);
563 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
565 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
567 pthread_mutex_unlock(&surface_queue->lock);
569 _tbm_surf_queue_mutex_unlock();
571 return TBM_SURFACE_QUEUE_ERROR_NONE;
574 tbm_surface_queue_error_e
575 tbm_surface_queue_remove_destroy_cb(
576 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
579 _tbm_surf_queue_mutex_lock();
581 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
582 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
584 pthread_mutex_lock(&surface_queue->lock);
586 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
588 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
590 pthread_mutex_unlock(&surface_queue->lock);
592 _tbm_surf_queue_mutex_unlock();
594 return TBM_SURFACE_QUEUE_ERROR_NONE;
597 tbm_surface_queue_error_e
598 tbm_surface_queue_add_dequeuable_cb(
599 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
602 _tbm_surf_queue_mutex_lock();
604 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
605 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
607 pthread_mutex_lock(&surface_queue->lock);
609 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
611 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
613 pthread_mutex_unlock(&surface_queue->lock);
615 _tbm_surf_queue_mutex_unlock();
617 return TBM_SURFACE_QUEUE_ERROR_NONE;
620 tbm_surface_queue_error_e
621 tbm_surface_queue_remove_dequeuable_cb(
622 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
625 _tbm_surf_queue_mutex_lock();
627 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
628 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
630 pthread_mutex_lock(&surface_queue->lock);
632 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
634 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
636 pthread_mutex_unlock(&surface_queue->lock);
638 _tbm_surf_queue_mutex_unlock();
640 return TBM_SURFACE_QUEUE_ERROR_NONE;
643 tbm_surface_queue_error_e
644 tbm_surface_queue_add_dequeue_cb(
645 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
648 _tbm_surf_queue_mutex_lock();
650 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
651 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
653 pthread_mutex_lock(&surface_queue->lock);
655 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
657 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
659 pthread_mutex_unlock(&surface_queue->lock);
661 _tbm_surf_queue_mutex_unlock();
663 return TBM_SURFACE_QUEUE_ERROR_NONE;
666 tbm_surface_queue_error_e
667 tbm_surface_queue_remove_dequeue_cb(
668 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
671 _tbm_surf_queue_mutex_lock();
673 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
674 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
676 pthread_mutex_lock(&surface_queue->lock);
678 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
680 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
682 pthread_mutex_unlock(&surface_queue->lock);
684 _tbm_surf_queue_mutex_unlock();
686 return TBM_SURFACE_QUEUE_ERROR_NONE;
689 tbm_surface_queue_error_e
690 tbm_surface_queue_add_acquirable_cb(
691 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
694 _tbm_surf_queue_mutex_lock();
696 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
697 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
699 pthread_mutex_lock(&surface_queue->lock);
701 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
703 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
705 pthread_mutex_unlock(&surface_queue->lock);
707 _tbm_surf_queue_mutex_unlock();
709 return TBM_SURFACE_QUEUE_ERROR_NONE;
712 tbm_surface_queue_error_e
713 tbm_surface_queue_remove_acquirable_cb(
714 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
717 _tbm_surf_queue_mutex_lock();
719 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
720 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
722 pthread_mutex_lock(&surface_queue->lock);
724 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
726 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
728 pthread_mutex_unlock(&surface_queue->lock);
730 _tbm_surf_queue_mutex_unlock();
732 return TBM_SURFACE_QUEUE_ERROR_NONE;
735 tbm_surface_queue_error_e
736 tbm_surface_queue_set_alloc_cb(
737 tbm_surface_queue_h surface_queue,
738 tbm_surface_alloc_cb alloc_cb,
739 tbm_surface_free_cb free_cb,
742 _tbm_surf_queue_mutex_lock();
744 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
745 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
747 pthread_mutex_lock(&surface_queue->lock);
749 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
751 surface_queue->alloc_cb = alloc_cb;
752 surface_queue->free_cb = free_cb;
753 surface_queue->alloc_cb_data = data;
755 pthread_mutex_unlock(&surface_queue->lock);
757 _tbm_surf_queue_mutex_unlock();
759 return TBM_SURFACE_QUEUE_ERROR_NONE;
763 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
767 _tbm_surf_queue_mutex_lock();
769 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
771 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
773 width = surface_queue->width;
775 _tbm_surf_queue_mutex_unlock();
781 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
785 _tbm_surf_queue_mutex_lock();
787 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
789 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
791 height = surface_queue->height;
793 _tbm_surf_queue_mutex_unlock();
799 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
803 _tbm_surf_queue_mutex_lock();
805 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
807 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
809 format = surface_queue->format;
811 _tbm_surf_queue_mutex_unlock();
817 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
821 _tbm_surf_queue_mutex_lock();
823 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
825 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
827 queue_size = surface_queue->queue_size;
829 _tbm_surf_queue_mutex_unlock();
834 tbm_surface_queue_error_e
835 tbm_surface_queue_add_reset_cb(
836 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
839 _tbm_surf_queue_mutex_lock();
841 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
842 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
844 pthread_mutex_lock(&surface_queue->lock);
846 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
848 _notify_add(&surface_queue->reset_noti, reset_cb, data);
850 pthread_mutex_unlock(&surface_queue->lock);
852 _tbm_surf_queue_mutex_unlock();
854 return TBM_SURFACE_QUEUE_ERROR_NONE;
857 tbm_surface_queue_error_e
858 tbm_surface_queue_remove_reset_cb(
859 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
862 _tbm_surf_queue_mutex_lock();
864 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
865 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
867 pthread_mutex_lock(&surface_queue->lock);
869 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
871 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
873 pthread_mutex_unlock(&surface_queue->lock);
875 _tbm_surf_queue_mutex_unlock();
877 return TBM_SURFACE_QUEUE_ERROR_NONE;
880 tbm_surface_queue_error_e
881 tbm_surface_queue_enqueue(tbm_surface_queue_h
882 surface_queue, tbm_surface_h surface)
884 queue_node *node = NULL;
887 _tbm_surf_queue_mutex_lock();
889 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
890 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
891 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
892 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
895 tbm_surface_internal_dump_buffer(surface, "enqueue");
897 pthread_mutex_lock(&surface_queue->lock);
899 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
901 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
902 if (node == NULL || queue_type != NODE_LIST) {
903 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
905 pthread_mutex_unlock(&surface_queue->lock);
907 _tbm_surf_queue_mutex_unlock();
908 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
911 if (surface_queue->impl && surface_queue->impl->enqueue)
912 surface_queue->impl->enqueue(surface_queue, node);
914 _tbm_surface_queue_enqueue(surface_queue, node, 1);
916 if (_queue_is_empty(&surface_queue->dirty_queue)) {
917 pthread_mutex_unlock(&surface_queue->lock);
919 _tbm_surf_queue_mutex_unlock();
920 return TBM_SURFACE_QUEUE_ERROR_NONE;
923 node->type = QUEUE_NODE_TYPE_ENQUEUE;
925 pthread_mutex_unlock(&surface_queue->lock);
926 pthread_cond_signal(&surface_queue->dirty_cond);
928 _tbm_surf_queue_mutex_unlock();
930 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
932 return TBM_SURFACE_QUEUE_ERROR_NONE;
935 tbm_surface_queue_error_e
936 tbm_surface_queue_dequeue(tbm_surface_queue_h
937 surface_queue, tbm_surface_h *surface)
939 queue_node *node = NULL;
941 _tbm_surf_queue_mutex_lock();
943 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
944 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
945 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
946 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
948 pthread_mutex_lock(&surface_queue->lock);
950 if (surface_queue->impl && surface_queue->impl->dequeue)
951 node = surface_queue->impl->dequeue(surface_queue);
953 node = _tbm_surface_queue_dequeue(surface_queue);
957 pthread_mutex_unlock(&surface_queue->lock);
959 _tbm_surf_queue_mutex_unlock();
960 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
963 if (node->surface == NULL) {
965 TBM_LOG_E("_queue_node_pop_front failed\n");
966 pthread_mutex_unlock(&surface_queue->lock);
968 _tbm_surf_queue_mutex_unlock();
969 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
972 node->type = QUEUE_NODE_TYPE_DEQUEUE;
973 *surface = node->surface;
975 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
977 pthread_mutex_unlock(&surface_queue->lock);
979 _tbm_surf_queue_mutex_unlock();
981 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
983 return TBM_SURFACE_QUEUE_ERROR_NONE;
987 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
989 _tbm_surf_queue_mutex_lock();
991 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
993 pthread_mutex_lock(&surface_queue->lock);
995 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
997 if (_queue_is_empty(&surface_queue->free_queue)) {
998 if (surface_queue->impl && surface_queue->impl->need_attach)
999 surface_queue->impl->need_attach(surface_queue);
1001 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1002 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1003 _tbm_surf_queue_mutex_unlock();
1008 if (_queue_is_empty(&surface_queue->free_queue)) {
1010 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) {
1012 _tbm_surf_queue_mutex_unlock();
1014 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1016 _tbm_surf_queue_mutex_lock();
1018 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1019 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1020 _tbm_surf_queue_mutex_unlock();
1024 pthread_mutex_unlock(&surface_queue->lock);
1026 _tbm_surf_queue_mutex_unlock();
1030 pthread_mutex_unlock(&surface_queue->lock);
1032 _tbm_surf_queue_mutex_unlock();
1036 pthread_mutex_unlock(&surface_queue->lock);
1038 _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)
1047 queue_node *node = NULL;
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 exist in free_queue or dirty_queue node:%p, queue:%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->impl && surface_queue->impl->release)
1072 surface_queue->impl->release(surface_queue, node);
1074 _tbm_surface_queue_release(surface_queue, node, 1);
1076 if (_queue_is_empty(&surface_queue->free_queue)) {
1077 pthread_mutex_unlock(&surface_queue->lock);
1079 _tbm_surf_queue_mutex_unlock();
1080 return TBM_SURFACE_QUEUE_ERROR_NONE;
1083 node->type = QUEUE_NODE_TYPE_RELEASE;
1085 pthread_mutex_unlock(&surface_queue->lock);
1086 pthread_cond_signal(&surface_queue->free_cond);
1088 _tbm_surf_queue_mutex_unlock();
1090 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1092 return TBM_SURFACE_QUEUE_ERROR_NONE;
1095 tbm_surface_queue_error_e
1096 tbm_surface_queue_acquire(tbm_surface_queue_h
1097 surface_queue, tbm_surface_h *surface)
1099 queue_node *node = NULL;
1101 _tbm_surf_queue_mutex_lock();
1103 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1104 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1105 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1106 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1108 pthread_mutex_lock(&surface_queue->lock);
1110 if (surface_queue->impl && surface_queue->impl->acquire)
1111 node = surface_queue->impl->acquire(surface_queue);
1113 node = _tbm_surface_queue_acquire(surface_queue);
1117 pthread_mutex_unlock(&surface_queue->lock);
1119 _tbm_surf_queue_mutex_unlock();
1120 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1123 if (node->surface == NULL) {
1125 TBM_LOG_E("_queue_node_pop_front failed\n");
1126 pthread_mutex_unlock(&surface_queue->lock);
1128 _tbm_surf_queue_mutex_unlock();
1129 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1132 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1134 *surface = node->surface;
1136 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1138 pthread_mutex_unlock(&surface_queue->lock);
1140 _tbm_surf_queue_mutex_unlock();
1143 tbm_surface_internal_dump_buffer(*surface, "acquire");
1145 return TBM_SURFACE_QUEUE_ERROR_NONE;
1149 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1151 _tbm_surf_queue_mutex_lock();
1153 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1155 pthread_mutex_lock(&surface_queue->lock);
1157 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1159 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1161 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
1163 _tbm_surf_queue_mutex_unlock();
1165 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1167 _tbm_surf_queue_mutex_lock();
1169 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1170 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1171 _tbm_surf_queue_mutex_unlock();
1175 pthread_mutex_unlock(&surface_queue->lock);
1177 _tbm_surf_queue_mutex_unlock();
1181 pthread_mutex_unlock(&surface_queue->lock);
1183 _tbm_surf_queue_mutex_unlock();
1187 pthread_mutex_unlock(&surface_queue->lock);
1189 _tbm_surf_queue_mutex_unlock();
1195 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1197 queue_node *node = NULL, *tmp = NULL;
1199 _tbm_surf_queue_mutex_lock();
1201 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1203 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1205 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1206 _queue_delete_node(surface_queue, node);
1209 if (surface_queue->impl && surface_queue->impl->destroy)
1210 surface_queue->impl->destroy(surface_queue);
1212 _notify_emit(surface_queue, &surface_queue->destory_noti);
1214 _notify_remove_all(&surface_queue->destory_noti);
1215 _notify_remove_all(&surface_queue->acquirable_noti);
1216 _notify_remove_all(&surface_queue->dequeuable_noti);
1217 _notify_remove_all(&surface_queue->reset_noti);
1219 pthread_mutex_destroy(&surface_queue->lock);
1221 LIST_DEL(&surface_queue->item_link);
1223 free(surface_queue);
1224 surface_queue = NULL;
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 = NULL;
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 return TBM_SURFACE_QUEUE_ERROR_NONE;
1249 pthread_mutex_lock(&surface_queue->lock);
1251 surface_queue->width = width;
1252 surface_queue->height = height;
1253 surface_queue->format = format;
1255 /* Destory surface and Push to free_queue */
1256 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1257 _queue_delete_node(surface_queue, node);
1261 _queue_init(&surface_queue->free_queue);
1262 _queue_init(&surface_queue->dirty_queue);
1263 LIST_INITHEAD(&surface_queue->list);
1265 if (surface_queue->impl && surface_queue->impl->reset)
1266 surface_queue->impl->reset(surface_queue);
1268 pthread_mutex_unlock(&surface_queue->lock);
1269 pthread_cond_signal(&surface_queue->free_cond);
1271 _tbm_surf_queue_mutex_unlock();
1273 _notify_emit(surface_queue, &surface_queue->reset_noti);
1275 return TBM_SURFACE_QUEUE_ERROR_NONE;
1278 tbm_surface_queue_error_e
1279 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1281 queue_node *node = NULL, *tmp = NULL;
1283 _tbm_surf_queue_mutex_lock();
1285 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1286 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1288 pthread_mutex_lock(&surface_queue->lock);
1290 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1292 /* Destory surface and Push to free_queue */
1293 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1294 _queue_delete_node(surface_queue, node);
1298 _queue_init(&surface_queue->free_queue);
1299 _queue_init(&surface_queue->dirty_queue);
1300 LIST_INITHEAD(&surface_queue->list);
1302 if (surface_queue->impl && surface_queue->impl->reset)
1303 surface_queue->impl->reset(surface_queue);
1305 pthread_mutex_unlock(&surface_queue->lock);
1306 pthread_cond_signal(&surface_queue->free_cond);
1308 _tbm_surf_queue_mutex_unlock();
1310 _notify_emit(surface_queue, &surface_queue->reset_noti);
1312 return TBM_SURFACE_QUEUE_ERROR_NONE;
1315 tbm_surface_queue_error_e
1316 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1317 tbm_surface_h *surfaces, int *num)
1319 queue_node *node = NULL;
1320 queue_node *tmp = NULL;
1322 _tbm_surf_queue_mutex_lock();
1324 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1325 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1326 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1327 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1329 pthread_mutex_lock(&surface_queue->lock);
1332 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1334 surfaces[*num] = node->surface;
1339 pthread_mutex_unlock(&surface_queue->lock);
1341 _tbm_surf_queue_mutex_unlock();
1343 return TBM_SURFACE_QUEUE_ERROR_NONE;
1350 } tbm_queue_default;
1353 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1355 tbm_queue_default *data = surface_queue->impl_data;
1357 data->num_attached = 0;
1361 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1363 tbm_queue_default *data = surface_queue->impl_data;
1365 data->num_attached = 0;
1369 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1371 free(surface_queue->impl_data);
1375 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1377 tbm_queue_default *data = surface_queue->impl_data;
1378 tbm_surface_h surface;
1380 if (data->queue_size == data->num_attached)
1383 if (surface_queue->alloc_cb) {
1385 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1386 TBM_RETURN_IF_FAIL(surface != NULL);
1387 tbm_surface_internal_ref(surface);
1389 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1390 surface_queue->height,
1391 surface_queue->format,
1393 TBM_RETURN_IF_FAIL(surface != NULL);
1396 _tbm_surface_queue_attach(surface_queue, surface);
1397 tbm_surface_internal_unref(surface);
1398 data->num_attached++;
1401 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1402 __tbm_queue_default_init,
1403 __tbm_queue_default_reset,
1404 __tbm_queue_default_destroy,
1405 __tbm_queue_default_need_attach,
1406 NULL, /*__tbm_queue_default_enqueue*/
1407 NULL, /*__tbm_queue_default_release*/
1408 NULL, /*__tbm_queue_default_dequeue*/
1409 NULL, /*__tbm_queue_default_acquire*/
1413 tbm_surface_queue_create(int queue_size, int width,
1414 int height, int format, int flags)
1416 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1417 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1418 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1419 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1421 _tbm_surf_queue_mutex_lock();
1423 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1424 sizeof(struct _tbm_surface_queue));
1425 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1427 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1429 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1430 sizeof(tbm_queue_default));
1432 free(surface_queue);
1433 _tbm_surf_queue_mutex_unlock();
1437 data->queue_size = queue_size;
1438 data->flags = flags;
1439 _tbm_surface_queue_init(surface_queue,
1441 width, height, format,
1442 &tbm_queue_default_impl, data);
1444 _tbm_surf_queue_mutex_unlock();
1446 return surface_queue;
1454 } tbm_queue_sequence;
1457 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1459 tbm_queue_sequence *data = surface_queue->impl_data;
1461 data->num_attached = 0;
1462 _queue_init(&data->dequeue_list);
1466 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1468 tbm_queue_sequence *data = surface_queue->impl_data;
1470 data->num_attached = 0;
1471 _queue_init(&data->dequeue_list);
1475 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1477 free(surface_queue->impl_data);
1481 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1483 tbm_queue_sequence *data = surface_queue->impl_data;
1484 tbm_surface_h surface;
1486 if (data->queue_size == data->num_attached)
1489 if (surface_queue->alloc_cb) {
1490 _tbm_surf_queue_mutex_unlock();
1491 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1492 _tbm_surf_queue_mutex_lock();
1497 tbm_surface_internal_ref(surface);
1499 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1500 surface_queue->height,
1501 surface_queue->format,
1503 TBM_RETURN_IF_FAIL(surface != NULL);
1506 _tbm_surface_queue_attach(surface_queue, surface);
1507 tbm_surface_internal_unref(surface);
1508 data->num_attached++;
1512 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1515 tbm_queue_sequence *data = surface_queue->impl_data;
1516 queue_node *next = NULL;
1517 queue_node *tmp = NULL;
1519 node->priv_flags = 0;
1521 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1522 if (next->priv_flags)
1524 _queue_node_pop(&data->dequeue_list, next);
1525 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1530 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1533 tbm_queue_sequence *data = surface_queue->impl_data;
1534 queue_node *node = NULL;
1536 node = _tbm_surface_queue_dequeue(surface_queue);
1538 _queue_node_push_back(&data->dequeue_list, node);
1539 node->priv_flags = 1;
1545 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1546 __tbm_queue_sequence_init,
1547 __tbm_queue_sequence_reset,
1548 __tbm_queue_sequence_destroy,
1549 __tbm_queue_sequence_need_attach,
1550 __tbm_queue_sequence_enqueue,
1551 NULL, /*__tbm_queue_sequence_release*/
1552 __tbm_queue_sequence_dequeue,
1553 NULL, /*__tbm_queue_sequence_acquire*/
1557 tbm_surface_queue_sequence_create(int queue_size, int width,
1558 int height, int format, int flags)
1560 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1561 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1562 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1563 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1565 _tbm_surf_queue_mutex_lock();
1567 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1568 sizeof(struct _tbm_surface_queue));
1569 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1571 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1573 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1574 sizeof(tbm_queue_sequence));
1576 free(surface_queue);
1580 data->queue_size = queue_size;
1581 data->flags = flags;
1582 _tbm_surface_queue_init(surface_queue,
1584 width, height, format,
1585 &tbm_queue_sequence_impl, data);
1587 _tbm_surf_queue_mutex_unlock();
1589 return surface_queue;
1591 /* LCOV_EXCL_STOP */