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 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
918 pthread_mutex_unlock(&surface_queue->lock);
920 _tbm_surf_queue_mutex_unlock();
921 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
924 node->type = QUEUE_NODE_TYPE_ENQUEUE;
926 pthread_mutex_unlock(&surface_queue->lock);
927 pthread_cond_signal(&surface_queue->dirty_cond);
929 _tbm_surf_queue_mutex_unlock();
931 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
933 return TBM_SURFACE_QUEUE_ERROR_NONE;
936 tbm_surface_queue_error_e
937 tbm_surface_queue_dequeue(tbm_surface_queue_h
938 surface_queue, tbm_surface_h *surface)
940 queue_node *node = NULL;
942 _tbm_surf_queue_mutex_lock();
944 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
945 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
946 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
947 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
949 pthread_mutex_lock(&surface_queue->lock);
951 if (surface_queue->impl && surface_queue->impl->dequeue)
952 node = surface_queue->impl->dequeue(surface_queue);
954 node = _tbm_surface_queue_dequeue(surface_queue);
958 pthread_mutex_unlock(&surface_queue->lock);
960 _tbm_surf_queue_mutex_unlock();
961 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
964 if (node->surface == NULL) {
966 TBM_LOG_E("_queue_node_pop_front failed\n");
967 pthread_mutex_unlock(&surface_queue->lock);
969 _tbm_surf_queue_mutex_unlock();
970 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
973 node->type = QUEUE_NODE_TYPE_DEQUEUE;
974 *surface = node->surface;
976 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
978 pthread_mutex_unlock(&surface_queue->lock);
980 _tbm_surf_queue_mutex_unlock();
982 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
984 return TBM_SURFACE_QUEUE_ERROR_NONE;
988 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
990 _tbm_surf_queue_mutex_lock();
992 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
994 pthread_mutex_lock(&surface_queue->lock);
996 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
998 if (_queue_is_empty(&surface_queue->free_queue)) {
999 if (surface_queue->impl && surface_queue->impl->need_attach)
1000 surface_queue->impl->need_attach(surface_queue);
1002 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1003 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1004 _tbm_surf_queue_mutex_unlock();
1009 if (_queue_is_empty(&surface_queue->free_queue)) {
1011 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) {
1013 _tbm_surf_queue_mutex_unlock();
1015 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1017 _tbm_surf_queue_mutex_lock();
1019 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1020 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1021 _tbm_surf_queue_mutex_unlock();
1025 pthread_mutex_unlock(&surface_queue->lock);
1027 _tbm_surf_queue_mutex_unlock();
1031 pthread_mutex_unlock(&surface_queue->lock);
1033 _tbm_surf_queue_mutex_unlock();
1037 pthread_mutex_unlock(&surface_queue->lock);
1039 _tbm_surf_queue_mutex_unlock();
1044 tbm_surface_queue_error_e
1045 tbm_surface_queue_release(tbm_surface_queue_h
1046 surface_queue, tbm_surface_h surface)
1048 queue_node *node = NULL;
1051 _tbm_surf_queue_mutex_lock();
1053 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1054 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1055 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1056 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1058 pthread_mutex_lock(&surface_queue->lock);
1060 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1062 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1063 if (node == NULL || queue_type != NODE_LIST) {
1064 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
1066 pthread_mutex_unlock(&surface_queue->lock);
1068 _tbm_surf_queue_mutex_unlock();
1069 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1072 if (surface_queue->impl && surface_queue->impl->release)
1073 surface_queue->impl->release(surface_queue, node);
1075 _tbm_surface_queue_release(surface_queue, node, 1);
1077 if (_queue_is_empty(&surface_queue->free_queue)) {
1078 pthread_mutex_unlock(&surface_queue->lock);
1080 _tbm_surf_queue_mutex_unlock();
1081 return TBM_SURFACE_QUEUE_ERROR_NONE;
1084 node->type = QUEUE_NODE_TYPE_RELEASE;
1086 pthread_mutex_unlock(&surface_queue->lock);
1087 pthread_cond_signal(&surface_queue->free_cond);
1089 _tbm_surf_queue_mutex_unlock();
1091 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1093 return TBM_SURFACE_QUEUE_ERROR_NONE;
1096 tbm_surface_queue_error_e
1097 tbm_surface_queue_acquire(tbm_surface_queue_h
1098 surface_queue, tbm_surface_h *surface)
1100 queue_node *node = NULL;
1102 _tbm_surf_queue_mutex_lock();
1104 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1105 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1106 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1107 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1109 pthread_mutex_lock(&surface_queue->lock);
1111 if (surface_queue->impl && surface_queue->impl->acquire)
1112 node = surface_queue->impl->acquire(surface_queue);
1114 node = _tbm_surface_queue_acquire(surface_queue);
1118 pthread_mutex_unlock(&surface_queue->lock);
1120 _tbm_surf_queue_mutex_unlock();
1121 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1124 if (node->surface == NULL) {
1126 TBM_LOG_E("_queue_node_pop_front failed\n");
1127 pthread_mutex_unlock(&surface_queue->lock);
1129 _tbm_surf_queue_mutex_unlock();
1130 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1133 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1135 *surface = node->surface;
1137 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1139 pthread_mutex_unlock(&surface_queue->lock);
1141 _tbm_surf_queue_mutex_unlock();
1144 tbm_surface_internal_dump_buffer(*surface, "acquire");
1146 return TBM_SURFACE_QUEUE_ERROR_NONE;
1150 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1152 _tbm_surf_queue_mutex_lock();
1154 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1156 pthread_mutex_lock(&surface_queue->lock);
1158 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1160 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1162 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
1164 _tbm_surf_queue_mutex_unlock();
1166 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1168 _tbm_surf_queue_mutex_lock();
1170 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1171 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1172 _tbm_surf_queue_mutex_unlock();
1176 pthread_mutex_unlock(&surface_queue->lock);
1178 _tbm_surf_queue_mutex_unlock();
1182 pthread_mutex_unlock(&surface_queue->lock);
1184 _tbm_surf_queue_mutex_unlock();
1188 pthread_mutex_unlock(&surface_queue->lock);
1190 _tbm_surf_queue_mutex_unlock();
1196 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1198 queue_node *node = NULL, *tmp = NULL;
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_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1207 _queue_delete_node(surface_queue, node);
1210 if (surface_queue->impl && surface_queue->impl->destroy)
1211 surface_queue->impl->destroy(surface_queue);
1213 _notify_emit(surface_queue, &surface_queue->destory_noti);
1215 _notify_remove_all(&surface_queue->destory_noti);
1216 _notify_remove_all(&surface_queue->acquirable_noti);
1217 _notify_remove_all(&surface_queue->dequeuable_noti);
1218 _notify_remove_all(&surface_queue->reset_noti);
1220 pthread_mutex_destroy(&surface_queue->lock);
1222 LIST_DEL(&surface_queue->item_link);
1224 free(surface_queue);
1225 surface_queue = NULL;
1227 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1228 _deinit_tbm_surf_queue_bufmgr();
1230 _tbm_surf_queue_mutex_unlock();
1233 tbm_surface_queue_error_e
1234 tbm_surface_queue_reset(tbm_surface_queue_h
1235 surface_queue, int width, int height, int format)
1237 queue_node *node = NULL, *tmp = NULL;
1239 _tbm_surf_queue_mutex_lock();
1241 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1242 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1244 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1246 if (width == surface_queue->width && height == surface_queue->height &&
1247 format == surface_queue->format) {
1248 _tbm_surf_queue_mutex_unlock();
1249 return TBM_SURFACE_QUEUE_ERROR_NONE;
1252 pthread_mutex_lock(&surface_queue->lock);
1254 surface_queue->width = width;
1255 surface_queue->height = height;
1256 surface_queue->format = format;
1258 /* Destory surface and Push to free_queue */
1259 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1260 _queue_delete_node(surface_queue, node);
1264 _queue_init(&surface_queue->free_queue);
1265 _queue_init(&surface_queue->dirty_queue);
1266 LIST_INITHEAD(&surface_queue->list);
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_flush(tbm_surface_queue_h surface_queue)
1284 queue_node *node = NULL, *tmp = NULL;
1286 _tbm_surf_queue_mutex_lock();
1288 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1289 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1291 pthread_mutex_lock(&surface_queue->lock);
1293 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1295 /* Destory surface and Push to free_queue */
1296 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1297 _queue_delete_node(surface_queue, node);
1301 _queue_init(&surface_queue->free_queue);
1302 _queue_init(&surface_queue->dirty_queue);
1303 LIST_INITHEAD(&surface_queue->list);
1305 if (surface_queue->impl && surface_queue->impl->reset)
1306 surface_queue->impl->reset(surface_queue);
1308 pthread_mutex_unlock(&surface_queue->lock);
1309 pthread_cond_signal(&surface_queue->free_cond);
1311 _tbm_surf_queue_mutex_unlock();
1313 _notify_emit(surface_queue, &surface_queue->reset_noti);
1315 return TBM_SURFACE_QUEUE_ERROR_NONE;
1318 tbm_surface_queue_error_e
1319 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1320 tbm_surface_h *surfaces, int *num)
1322 queue_node *node = NULL;
1323 queue_node *tmp = NULL;
1325 _tbm_surf_queue_mutex_lock();
1327 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1328 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1329 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1330 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1332 pthread_mutex_lock(&surface_queue->lock);
1335 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1337 surfaces[*num] = node->surface;
1342 pthread_mutex_unlock(&surface_queue->lock);
1344 _tbm_surf_queue_mutex_unlock();
1346 return TBM_SURFACE_QUEUE_ERROR_NONE;
1353 } tbm_queue_default;
1356 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1358 tbm_queue_default *data = surface_queue->impl_data;
1360 data->num_attached = 0;
1364 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1366 tbm_queue_default *data = surface_queue->impl_data;
1368 data->num_attached = 0;
1372 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1374 free(surface_queue->impl_data);
1378 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1380 tbm_queue_default *data = surface_queue->impl_data;
1381 tbm_surface_h surface;
1383 if (data->queue_size == data->num_attached)
1386 if (surface_queue->alloc_cb) {
1387 _tbm_surf_queue_mutex_unlock();
1388 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1389 _tbm_surf_queue_mutex_lock();
1394 tbm_surface_internal_ref(surface);
1396 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1397 surface_queue->height,
1398 surface_queue->format,
1400 TBM_RETURN_IF_FAIL(surface != NULL);
1403 _tbm_surface_queue_attach(surface_queue, surface);
1404 tbm_surface_internal_unref(surface);
1405 data->num_attached++;
1408 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1409 __tbm_queue_default_init,
1410 __tbm_queue_default_reset,
1411 __tbm_queue_default_destroy,
1412 __tbm_queue_default_need_attach,
1413 NULL, /*__tbm_queue_default_enqueue*/
1414 NULL, /*__tbm_queue_default_release*/
1415 NULL, /*__tbm_queue_default_dequeue*/
1416 NULL, /*__tbm_queue_default_acquire*/
1420 tbm_surface_queue_create(int queue_size, int width,
1421 int height, int format, int flags)
1423 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1424 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1425 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1426 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1428 _tbm_surf_queue_mutex_lock();
1430 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1431 sizeof(struct _tbm_surface_queue));
1432 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1434 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1436 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1437 sizeof(tbm_queue_default));
1439 free(surface_queue);
1440 _tbm_surf_queue_mutex_unlock();
1444 data->queue_size = queue_size;
1445 data->flags = flags;
1446 _tbm_surface_queue_init(surface_queue,
1448 width, height, format,
1449 &tbm_queue_default_impl, data);
1451 _tbm_surf_queue_mutex_unlock();
1453 return surface_queue;
1461 } tbm_queue_sequence;
1464 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1466 tbm_queue_sequence *data = surface_queue->impl_data;
1468 data->num_attached = 0;
1469 _queue_init(&data->dequeue_list);
1473 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1475 tbm_queue_sequence *data = surface_queue->impl_data;
1477 data->num_attached = 0;
1478 _queue_init(&data->dequeue_list);
1482 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1484 free(surface_queue->impl_data);
1488 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1490 tbm_queue_sequence *data = surface_queue->impl_data;
1491 tbm_surface_h surface;
1493 if (data->queue_size == data->num_attached)
1496 if (surface_queue->alloc_cb) {
1497 _tbm_surf_queue_mutex_unlock();
1498 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1499 _tbm_surf_queue_mutex_lock();
1504 tbm_surface_internal_ref(surface);
1506 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1507 surface_queue->height,
1508 surface_queue->format,
1510 TBM_RETURN_IF_FAIL(surface != NULL);
1513 _tbm_surface_queue_attach(surface_queue, surface);
1514 tbm_surface_internal_unref(surface);
1515 data->num_attached++;
1519 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1522 tbm_queue_sequence *data = surface_queue->impl_data;
1523 queue_node *next = NULL;
1524 queue_node *tmp = NULL;
1526 node->priv_flags = 0;
1528 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1529 if (next->priv_flags)
1531 _queue_node_pop(&data->dequeue_list, next);
1532 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1537 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1540 tbm_queue_sequence *data = surface_queue->impl_data;
1541 queue_node *node = NULL;
1543 node = _tbm_surface_queue_dequeue(surface_queue);
1545 _queue_node_push_back(&data->dequeue_list, node);
1546 node->priv_flags = 1;
1552 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1553 __tbm_queue_sequence_init,
1554 __tbm_queue_sequence_reset,
1555 __tbm_queue_sequence_destroy,
1556 __tbm_queue_sequence_need_attach,
1557 __tbm_queue_sequence_enqueue,
1558 NULL, /*__tbm_queue_sequence_release*/
1559 __tbm_queue_sequence_dequeue,
1560 NULL, /*__tbm_queue_sequence_acquire*/
1564 tbm_surface_queue_sequence_create(int queue_size, int width,
1565 int height, int format, int flags)
1567 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1568 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1569 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1570 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1572 _tbm_surf_queue_mutex_lock();
1574 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1575 sizeof(struct _tbm_surface_queue));
1576 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1578 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1580 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1581 sizeof(tbm_queue_sequence));
1583 free(surface_queue);
1587 data->queue_size = queue_size;
1588 data->flags = flags;
1589 _tbm_surface_queue_init(surface_queue,
1591 width, height, format,
1592 &tbm_queue_sequence_impl, data);
1594 _tbm_surf_queue_mutex_unlock();
1596 return surface_queue;
1598 /* LCOV_EXCL_STOP */