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 return TBM_SURFACE_QUEUE_ERROR_NONE;
1250 pthread_mutex_lock(&surface_queue->lock);
1252 surface_queue->width = width;
1253 surface_queue->height = height;
1254 surface_queue->format = format;
1256 /* Destory surface and Push to free_queue */
1257 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1258 _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 if (surface_queue->impl && surface_queue->impl->reset)
1267 surface_queue->impl->reset(surface_queue);
1269 pthread_mutex_unlock(&surface_queue->lock);
1270 pthread_cond_signal(&surface_queue->free_cond);
1272 _tbm_surf_queue_mutex_unlock();
1274 _notify_emit(surface_queue, &surface_queue->reset_noti);
1276 return TBM_SURFACE_QUEUE_ERROR_NONE;
1279 tbm_surface_queue_error_e
1280 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1282 queue_node *node = NULL, *tmp = NULL;
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 pthread_mutex_lock(&surface_queue->lock);
1291 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1293 /* Destory surface and Push to free_queue */
1294 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1295 _queue_delete_node(surface_queue, node);
1299 _queue_init(&surface_queue->free_queue);
1300 _queue_init(&surface_queue->dirty_queue);
1301 LIST_INITHEAD(&surface_queue->list);
1303 if (surface_queue->impl && surface_queue->impl->reset)
1304 surface_queue->impl->reset(surface_queue);
1306 pthread_mutex_unlock(&surface_queue->lock);
1307 pthread_cond_signal(&surface_queue->free_cond);
1309 _tbm_surf_queue_mutex_unlock();
1311 _notify_emit(surface_queue, &surface_queue->reset_noti);
1313 return TBM_SURFACE_QUEUE_ERROR_NONE;
1316 tbm_surface_queue_error_e
1317 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1318 tbm_surface_h *surfaces, int *num)
1320 queue_node *node = NULL;
1321 queue_node *tmp = NULL;
1323 _tbm_surf_queue_mutex_lock();
1325 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1326 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1327 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1328 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1330 pthread_mutex_lock(&surface_queue->lock);
1333 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1335 surfaces[*num] = node->surface;
1340 pthread_mutex_unlock(&surface_queue->lock);
1342 _tbm_surf_queue_mutex_unlock();
1344 return TBM_SURFACE_QUEUE_ERROR_NONE;
1351 } tbm_queue_default;
1354 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1356 tbm_queue_default *data = surface_queue->impl_data;
1358 data->num_attached = 0;
1362 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1364 tbm_queue_default *data = surface_queue->impl_data;
1366 data->num_attached = 0;
1370 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1372 free(surface_queue->impl_data);
1376 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1378 tbm_queue_default *data = surface_queue->impl_data;
1379 tbm_surface_h surface;
1381 if (data->queue_size == data->num_attached)
1384 if (surface_queue->alloc_cb) {
1386 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1387 TBM_RETURN_IF_FAIL(surface != NULL);
1388 tbm_surface_internal_ref(surface);
1390 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1391 surface_queue->height,
1392 surface_queue->format,
1394 TBM_RETURN_IF_FAIL(surface != NULL);
1397 _tbm_surface_queue_attach(surface_queue, surface);
1398 tbm_surface_internal_unref(surface);
1399 data->num_attached++;
1402 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1403 __tbm_queue_default_init,
1404 __tbm_queue_default_reset,
1405 __tbm_queue_default_destroy,
1406 __tbm_queue_default_need_attach,
1407 NULL, /*__tbm_queue_default_enqueue*/
1408 NULL, /*__tbm_queue_default_release*/
1409 NULL, /*__tbm_queue_default_dequeue*/
1410 NULL, /*__tbm_queue_default_acquire*/
1414 tbm_surface_queue_create(int queue_size, int width,
1415 int height, int format, int flags)
1417 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1418 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1419 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1420 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1422 _tbm_surf_queue_mutex_lock();
1424 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1425 sizeof(struct _tbm_surface_queue));
1426 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1428 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1430 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1431 sizeof(tbm_queue_default));
1433 free(surface_queue);
1434 _tbm_surf_queue_mutex_unlock();
1438 data->queue_size = queue_size;
1439 data->flags = flags;
1440 _tbm_surface_queue_init(surface_queue,
1442 width, height, format,
1443 &tbm_queue_default_impl, data);
1445 _tbm_surf_queue_mutex_unlock();
1447 return surface_queue;
1455 } tbm_queue_sequence;
1458 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1460 tbm_queue_sequence *data = surface_queue->impl_data;
1462 data->num_attached = 0;
1463 _queue_init(&data->dequeue_list);
1467 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1469 tbm_queue_sequence *data = surface_queue->impl_data;
1471 data->num_attached = 0;
1472 _queue_init(&data->dequeue_list);
1476 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1478 free(surface_queue->impl_data);
1482 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1484 tbm_queue_sequence *data = surface_queue->impl_data;
1485 tbm_surface_h surface;
1487 if (data->queue_size == data->num_attached)
1490 if (surface_queue->alloc_cb) {
1491 _tbm_surf_queue_mutex_unlock();
1492 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1493 _tbm_surf_queue_mutex_lock();
1498 tbm_surface_internal_ref(surface);
1500 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1501 surface_queue->height,
1502 surface_queue->format,
1504 TBM_RETURN_IF_FAIL(surface != NULL);
1507 _tbm_surface_queue_attach(surface_queue, surface);
1508 tbm_surface_internal_unref(surface);
1509 data->num_attached++;
1513 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1516 tbm_queue_sequence *data = surface_queue->impl_data;
1517 queue_node *next = NULL;
1518 queue_node *tmp = NULL;
1520 node->priv_flags = 0;
1522 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1523 if (next->priv_flags)
1525 _queue_node_pop(&data->dequeue_list, next);
1526 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1531 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1534 tbm_queue_sequence *data = surface_queue->impl_data;
1535 queue_node *node = NULL;
1537 node = _tbm_surface_queue_dequeue(surface_queue);
1539 _queue_node_push_back(&data->dequeue_list, node);
1540 node->priv_flags = 1;
1546 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1547 __tbm_queue_sequence_init,
1548 __tbm_queue_sequence_reset,
1549 __tbm_queue_sequence_destroy,
1550 __tbm_queue_sequence_need_attach,
1551 __tbm_queue_sequence_enqueue,
1552 NULL, /*__tbm_queue_sequence_release*/
1553 __tbm_queue_sequence_dequeue,
1554 NULL, /*__tbm_queue_sequence_acquire*/
1558 tbm_surface_queue_sequence_create(int queue_size, int width,
1559 int height, int format, int flags)
1561 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1562 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1563 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1564 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1566 _tbm_surf_queue_mutex_lock();
1568 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1569 sizeof(struct _tbm_surface_queue));
1570 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1572 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1574 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1575 sizeof(tbm_queue_sequence));
1577 free(surface_queue);
1581 data->queue_size = queue_size;
1582 data->flags = flags;
1583 _tbm_surface_queue_init(surface_queue,
1585 width, height, format,
1586 &tbm_queue_sequence_impl, data);
1588 _tbm_surf_queue_mutex_unlock();
1590 return surface_queue;
1592 /* LCOV_EXCL_STOP */