1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 #include "tbm_bufmgr_int.h"
41 #define TBM_QUEUE_DEBUG 0
44 #define TBM_QUEUE_TRACE(fmt, ...) { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
46 #define TBM_QUEUE_TRACE(fmt, ...)
50 #define TBM_LOCK() TBM_LOG_D("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
51 #define TBM_UNLOCK() TBM_LOG_D("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
57 static tbm_bufmgr g_surf_queue_bufmgr;
58 static pthread_mutex_t tbm_surf_queue_lock;
59 void _tbm_surface_queue_mutex_unlock(void);
62 #define TBM_SURF_QUEUE_RETURN_IF_FAIL(cond) {\
64 TBM_LOG_E("'%s' failed.\n", #cond);\
65 _tbm_surf_queue_mutex_unlock();\
70 #define TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(cond, val) {\
72 TBM_LOG_E("'%s' failed.\n", #cond);\
73 _tbm_surf_queue_mutex_unlock();\
78 typedef enum _queue_node_type {
80 QUEUE_NODE_TYPE_DEQUEUE,
81 QUEUE_NODE_TYPE_ENQUEUE,
82 QUEUE_NODE_TYPE_ACQUIRE,
83 QUEUE_NODE_TYPE_RELEASE
87 struct list_head head;
92 tbm_surface_h surface;
94 struct list_head item_link;
95 struct list_head link;
99 unsigned int priv_flags; /*for each queue*/
105 struct list_head link;
107 tbm_surface_queue_notify_cb cb;
112 struct list_head link;
114 tbm_surface_queue_trace_cb cb;
118 typedef struct _tbm_surface_queue_interface {
119 void (*init)(tbm_surface_queue_h queue);
120 void (*reset)(tbm_surface_queue_h queue);
121 void (*destroy)(tbm_surface_queue_h queue);
122 void (*need_attach)(tbm_surface_queue_h queue);
124 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
125 void (*release)(tbm_surface_queue_h queue, queue_node *node);
126 queue_node *(*dequeue)(tbm_surface_queue_h queue);
127 queue_node *(*acquire)(tbm_surface_queue_h queue);
128 void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
129 } tbm_surface_queue_interface;
131 struct _tbm_surface_queue {
140 struct list_head list;
142 struct list_head destory_noti;
143 struct list_head dequeuable_noti;
144 struct list_head dequeue_noti;
145 struct list_head can_dequeue_noti;
146 struct list_head acquirable_noti;
147 struct list_head reset_noti;
148 struct list_head trace_noti;
150 pthread_mutex_t lock;
151 pthread_cond_t free_cond;
152 pthread_cond_t dirty_cond;
154 const tbm_surface_queue_interface *impl;
157 //For external buffer allocation
158 tbm_surface_alloc_cb alloc_cb;
159 tbm_surface_free_cb free_cb;
162 struct list_head item_link; /* link of surface queue */
168 _tbm_surf_queue_mutex_init(void)
170 static bool tbm_surf_queue_mutex_init = false;
172 if (tbm_surf_queue_mutex_init)
175 if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
176 TBM_LOG_E("fail: pthread_mutex_init\n");
180 tbm_surf_queue_mutex_init = true;
186 _tbm_surf_queue_mutex_lock(void)
188 if (!_tbm_surf_queue_mutex_init()) {
189 TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n");
193 pthread_mutex_lock(&tbm_surf_queue_lock);
197 _tbm_surf_queue_mutex_unlock(void)
199 pthread_mutex_unlock(&tbm_surf_queue_lock);
203 _init_tbm_surf_queue_bufmgr(void)
205 g_surf_queue_bufmgr = tbm_bufmgr_init(-1);
209 _deinit_tbm_surf_queue_bufmgr(void)
211 if (!g_surf_queue_bufmgr)
214 tbm_bufmgr_deinit(g_surf_queue_bufmgr);
215 g_surf_queue_bufmgr = NULL;
219 _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
221 tbm_surface_queue_h old_data = NULL;
223 if (surface_queue == NULL) {
224 TBM_LOG_E("error: surface_queue is NULL.\n");
228 if (g_surf_queue_bufmgr == NULL) {
229 TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n");
233 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
234 TBM_LOG_E("error: surf_queue_list is empty\n");
238 LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
240 if (old_data == surface_queue) {
241 TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue);
246 TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
252 _queue_node_create(void)
254 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
256 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
262 _queue_node_delete(queue_node *node)
264 LIST_DEL(&node->item_link);
265 LIST_DEL(&node->link);
270 _queue_is_empty(queue *queue)
272 if (LIST_IS_EMPTY(&queue->head))
279 _queue_node_push_back(queue *queue, queue_node *node)
281 LIST_ADDTAIL(&node->item_link, &queue->head);
286 _queue_node_push_front(queue *queue, queue_node *node)
288 LIST_ADD(&node->item_link, &queue->head);
293 _queue_node_pop_front(queue *queue)
297 if (!queue->head.next) return NULL;
298 if (!queue->count) return NULL;
300 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
302 LIST_DELINIT(&node->item_link);
309 _queue_node_pop(queue *queue, queue_node *node)
311 LIST_DELINIT(&node->item_link);
318 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
319 tbm_surface_h surface, int *out_type)
321 queue_node *node = NULL;
324 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
328 if (type & FREE_QUEUE) {
329 LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head,
331 if (node->surface == surface) {
333 *out_type = FREE_QUEUE;
340 if (type & DIRTY_QUEUE) {
341 LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head,
343 if (node->surface == surface) {
345 *out_type = DIRTY_QUEUE;
352 if (type & NODE_LIST) {
353 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
354 if (node->surface == surface) {
356 *out_type = NODE_LIST;
363 TBM_LOG_E("fail to get the queue_node.\n");
369 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
372 if (surface_queue->free_cb) {
373 surface_queue->free_cb(surface_queue,
374 surface_queue->alloc_cb_data,
378 tbm_surface_destroy(node->surface);
381 _queue_node_delete(node);
385 _queue_init(queue *queue)
387 LIST_INITHEAD(&queue->head);
393 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
396 TBM_RETURN_IF_FAIL(cb != NULL);
398 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
400 TBM_RETURN_IF_FAIL(item != NULL);
402 LIST_INITHEAD(&item->link);
406 LIST_ADDTAIL(&item->link, list);
410 _notify_remove(struct list_head *list,
411 tbm_surface_queue_notify_cb cb, void *data)
413 queue_notify *item = NULL, *tmp;
415 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
416 if (item->cb == cb && item->data == data) {
417 LIST_DEL(&item->link);
423 TBM_LOG_E("Cannot find notifiy\n");
427 _notify_remove_all(struct list_head *list)
429 queue_notify *item = NULL, *tmp;
431 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
432 LIST_DEL(&item->link);
438 _notify_emit(tbm_surface_queue_h surface_queue,
439 struct list_head *list)
441 queue_notify *item = NULL, *tmp;;
444 The item->cb is the outside function of the libtbm.
445 The tbm user may/can remove the item of the list,
446 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
448 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
449 item->cb(surface_queue, item->data);
453 _trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
456 TBM_RETURN_IF_FAIL(cb != NULL);
458 queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
460 TBM_RETURN_IF_FAIL(item != NULL);
462 LIST_INITHEAD(&item->link);
466 LIST_ADDTAIL(&item->link, list);
470 _trace_remove(struct list_head *list,
471 tbm_surface_queue_trace_cb cb, void *data)
473 queue_trace *item = NULL, *tmp;
475 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
476 if (item->cb == cb && item->data == data) {
477 LIST_DEL(&item->link);
483 TBM_LOG_E("Cannot find notifiy\n");
487 _trace_remove_all(struct list_head *list)
489 queue_trace *item = NULL, *tmp;
491 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
492 LIST_DEL(&item->link);
498 _trace_emit(tbm_surface_queue_h surface_queue,
499 struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
501 queue_trace *item = NULL, *tmp;;
504 The item->cb is the outside function of the libtbm.
505 The tbm user may/can remove the item of the list,
506 so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
508 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
509 item->cb(surface_queue, surface, trace, item->data);
513 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
515 queue_node *node = NULL;
518 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
519 if (node->type == type)
527 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
528 tbm_surface_h surface)
532 node = _queue_node_create();
533 TBM_RETURN_IF_FAIL(node != NULL);
535 tbm_surface_internal_ref(surface);
536 node->surface = surface;
538 LIST_ADDTAIL(&node->link, &surface_queue->list);
539 surface_queue->num_attached++;
540 _queue_node_push_back(&surface_queue->free_queue, node);
544 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
545 tbm_surface_h surface)
550 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
552 _queue_delete_node(surface_queue, node);
553 surface_queue->num_attached--;
558 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
559 queue_node *node, int push_back)
562 _queue_node_push_back(&surface_queue->dirty_queue, node);
564 _queue_node_push_front(&surface_queue->dirty_queue, node);
568 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
572 node = _queue_node_pop_front(&surface_queue->free_queue);
578 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
582 if (_queue_is_empty(&surface_queue->dirty_queue))
585 node = _queue_node_pop_front(&surface_queue->dirty_queue);
591 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
592 queue_node *node, int push_back)
595 _queue_node_push_back(&surface_queue->free_queue, node);
597 _queue_node_push_front(&surface_queue->free_queue, node);
601 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
603 int width, int height, int format,
604 const tbm_surface_queue_interface *impl, void *data)
606 TBM_RETURN_IF_FAIL(surface_queue != NULL);
607 TBM_RETURN_IF_FAIL(impl != NULL);
609 if (!g_surf_queue_bufmgr)
610 _init_tbm_surf_queue_bufmgr();
612 pthread_mutex_init(&surface_queue->lock, NULL);
613 pthread_cond_init(&surface_queue->free_cond, NULL);
614 pthread_cond_init(&surface_queue->dirty_cond, NULL);
616 surface_queue->queue_size = queue_size;
617 surface_queue->width = width;
618 surface_queue->height = height;
619 surface_queue->format = format;
620 surface_queue->impl = impl;
621 surface_queue->impl_data = data;
622 surface_queue->modes = TBM_SURFACE_QUEUE_MODE_NONE;
624 _queue_init(&surface_queue->free_queue);
625 _queue_init(&surface_queue->dirty_queue);
626 LIST_INITHEAD(&surface_queue->list);
628 LIST_INITHEAD(&surface_queue->destory_noti);
629 LIST_INITHEAD(&surface_queue->dequeuable_noti);
630 LIST_INITHEAD(&surface_queue->dequeue_noti);
631 LIST_INITHEAD(&surface_queue->can_dequeue_noti);
632 LIST_INITHEAD(&surface_queue->acquirable_noti);
633 LIST_INITHEAD(&surface_queue->reset_noti);
634 LIST_INITHEAD(&surface_queue->trace_noti);
636 if (surface_queue->impl && surface_queue->impl->init)
637 surface_queue->impl->init(surface_queue);
639 LIST_ADD(&surface_queue->item_link, &g_surf_queue_bufmgr->surf_queue_list);
642 tbm_surface_queue_error_e
643 tbm_surface_queue_add_destroy_cb(
644 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
647 _tbm_surf_queue_mutex_lock();
649 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
650 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
652 pthread_mutex_lock(&surface_queue->lock);
654 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
656 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
658 pthread_mutex_unlock(&surface_queue->lock);
660 _tbm_surf_queue_mutex_unlock();
662 return TBM_SURFACE_QUEUE_ERROR_NONE;
665 tbm_surface_queue_error_e
666 tbm_surface_queue_remove_destroy_cb(
667 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
670 _tbm_surf_queue_mutex_lock();
672 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
673 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
675 pthread_mutex_lock(&surface_queue->lock);
677 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
679 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
681 pthread_mutex_unlock(&surface_queue->lock);
683 _tbm_surf_queue_mutex_unlock();
685 return TBM_SURFACE_QUEUE_ERROR_NONE;
688 tbm_surface_queue_error_e
689 tbm_surface_queue_add_dequeuable_cb(
690 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
693 _tbm_surf_queue_mutex_lock();
695 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
696 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
698 pthread_mutex_lock(&surface_queue->lock);
700 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
702 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
704 pthread_mutex_unlock(&surface_queue->lock);
706 _tbm_surf_queue_mutex_unlock();
708 return TBM_SURFACE_QUEUE_ERROR_NONE;
711 tbm_surface_queue_error_e
712 tbm_surface_queue_remove_dequeuable_cb(
713 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
716 _tbm_surf_queue_mutex_lock();
718 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
719 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
721 pthread_mutex_lock(&surface_queue->lock);
723 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
725 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
727 pthread_mutex_unlock(&surface_queue->lock);
729 _tbm_surf_queue_mutex_unlock();
731 return TBM_SURFACE_QUEUE_ERROR_NONE;
734 tbm_surface_queue_error_e
735 tbm_surface_queue_add_dequeue_cb(
736 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
739 _tbm_surf_queue_mutex_lock();
741 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
742 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
744 pthread_mutex_lock(&surface_queue->lock);
746 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
748 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
750 pthread_mutex_unlock(&surface_queue->lock);
752 _tbm_surf_queue_mutex_unlock();
754 return TBM_SURFACE_QUEUE_ERROR_NONE;
757 tbm_surface_queue_error_e
758 tbm_surface_queue_remove_dequeue_cb(
759 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
762 _tbm_surf_queue_mutex_lock();
764 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
765 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
767 pthread_mutex_lock(&surface_queue->lock);
769 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
771 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
773 pthread_mutex_unlock(&surface_queue->lock);
775 _tbm_surf_queue_mutex_unlock();
777 return TBM_SURFACE_QUEUE_ERROR_NONE;
780 tbm_surface_queue_error_e
781 tbm_surface_queue_add_can_dequeue_cb(
782 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
785 _tbm_surf_queue_mutex_lock();
787 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
788 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
790 pthread_mutex_lock(&surface_queue->lock);
792 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
794 _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
796 pthread_mutex_unlock(&surface_queue->lock);
798 _tbm_surf_queue_mutex_unlock();
800 return TBM_SURFACE_QUEUE_ERROR_NONE;
803 tbm_surface_queue_error_e
804 tbm_surface_queue_remove_can_dequeue_cb(
805 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
808 _tbm_surf_queue_mutex_lock();
810 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
811 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
813 pthread_mutex_lock(&surface_queue->lock);
815 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
817 _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
819 pthread_mutex_unlock(&surface_queue->lock);
821 _tbm_surf_queue_mutex_unlock();
823 return TBM_SURFACE_QUEUE_ERROR_NONE;
826 tbm_surface_queue_error_e
827 tbm_surface_queue_add_acquirable_cb(
828 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
831 _tbm_surf_queue_mutex_lock();
833 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
834 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
836 pthread_mutex_lock(&surface_queue->lock);
838 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
840 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
842 pthread_mutex_unlock(&surface_queue->lock);
844 _tbm_surf_queue_mutex_unlock();
846 return TBM_SURFACE_QUEUE_ERROR_NONE;
849 tbm_surface_queue_error_e
850 tbm_surface_queue_remove_acquirable_cb(
851 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
854 _tbm_surf_queue_mutex_lock();
856 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
857 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
859 pthread_mutex_lock(&surface_queue->lock);
861 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
863 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
865 pthread_mutex_unlock(&surface_queue->lock);
867 _tbm_surf_queue_mutex_unlock();
869 return TBM_SURFACE_QUEUE_ERROR_NONE;
872 tbm_surface_queue_error_e
873 tbm_surface_queue_add_trace_cb(
874 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
877 _tbm_surf_queue_mutex_lock();
879 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
880 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
882 pthread_mutex_lock(&surface_queue->lock);
884 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
886 _trace_add(&surface_queue->trace_noti, trace_cb, data);
888 pthread_mutex_unlock(&surface_queue->lock);
890 _tbm_surf_queue_mutex_unlock();
892 return TBM_SURFACE_QUEUE_ERROR_NONE;
895 tbm_surface_queue_error_e
896 tbm_surface_queue_remove_trace_cb(
897 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
900 _tbm_surf_queue_mutex_lock();
902 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
903 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
905 pthread_mutex_lock(&surface_queue->lock);
907 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
909 _trace_remove(&surface_queue->trace_noti, trace_cb, data);
911 pthread_mutex_unlock(&surface_queue->lock);
913 _tbm_surf_queue_mutex_unlock();
915 return TBM_SURFACE_QUEUE_ERROR_NONE;
918 tbm_surface_queue_error_e
919 tbm_surface_queue_set_alloc_cb(
920 tbm_surface_queue_h surface_queue,
921 tbm_surface_alloc_cb alloc_cb,
922 tbm_surface_free_cb free_cb,
925 _tbm_surf_queue_mutex_lock();
927 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
928 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
930 pthread_mutex_lock(&surface_queue->lock);
932 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
934 surface_queue->alloc_cb = alloc_cb;
935 surface_queue->free_cb = free_cb;
936 surface_queue->alloc_cb_data = data;
938 pthread_mutex_unlock(&surface_queue->lock);
940 _tbm_surf_queue_mutex_unlock();
942 return TBM_SURFACE_QUEUE_ERROR_NONE;
946 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
950 _tbm_surf_queue_mutex_lock();
952 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
954 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
956 width = surface_queue->width;
958 _tbm_surf_queue_mutex_unlock();
964 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
968 _tbm_surf_queue_mutex_lock();
970 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
972 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
974 height = surface_queue->height;
976 _tbm_surf_queue_mutex_unlock();
982 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
986 _tbm_surf_queue_mutex_lock();
988 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
990 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
992 format = surface_queue->format;
994 _tbm_surf_queue_mutex_unlock();
1000 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
1004 _tbm_surf_queue_mutex_lock();
1006 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1008 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1010 queue_size = surface_queue->queue_size;
1012 _tbm_surf_queue_mutex_unlock();
1017 tbm_surface_queue_error_e
1018 tbm_surface_queue_add_reset_cb(
1019 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1022 _tbm_surf_queue_mutex_lock();
1024 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1025 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1027 pthread_mutex_lock(&surface_queue->lock);
1029 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1031 _notify_add(&surface_queue->reset_noti, reset_cb, data);
1033 pthread_mutex_unlock(&surface_queue->lock);
1035 _tbm_surf_queue_mutex_unlock();
1037 return TBM_SURFACE_QUEUE_ERROR_NONE;
1040 tbm_surface_queue_error_e
1041 tbm_surface_queue_remove_reset_cb(
1042 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
1045 _tbm_surf_queue_mutex_lock();
1047 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1048 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1050 pthread_mutex_lock(&surface_queue->lock);
1052 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1054 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
1056 pthread_mutex_unlock(&surface_queue->lock);
1058 _tbm_surf_queue_mutex_unlock();
1060 return TBM_SURFACE_QUEUE_ERROR_NONE;
1063 tbm_surface_queue_error_e
1064 tbm_surface_queue_enqueue(tbm_surface_queue_h
1065 surface_queue, tbm_surface_h surface)
1070 _tbm_surf_queue_mutex_lock();
1072 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1073 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1074 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1075 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1078 tbm_surface_internal_dump_buffer(surface, "enqueue");
1080 pthread_mutex_lock(&surface_queue->lock);
1082 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1084 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1085 if (node == NULL || queue_type != NODE_LIST) {
1086 TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1088 pthread_mutex_unlock(&surface_queue->lock);
1090 _tbm_surf_queue_mutex_unlock();
1093 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1095 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1098 if (surface_queue->impl && surface_queue->impl->enqueue)
1099 surface_queue->impl->enqueue(surface_queue, node);
1101 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1103 if (!_queue_get_node(surface_queue, DIRTY_QUEUE, surface, NULL)) {
1104 TBM_LOG_E("enqueue surface(%p) but surface isn't present in the dirty_queue\n", surface);
1105 pthread_mutex_unlock(&surface_queue->lock);
1107 _tbm_surf_queue_mutex_unlock();
1108 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1111 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1113 pthread_mutex_unlock(&surface_queue->lock);
1114 pthread_cond_signal(&surface_queue->dirty_cond);
1116 _tbm_surf_queue_mutex_unlock();
1118 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
1120 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1122 return TBM_SURFACE_QUEUE_ERROR_NONE;
1125 tbm_surface_queue_error_e
1126 tbm_surface_queue_cancel_dequeue(tbm_surface_queue_h
1127 surface_queue, tbm_surface_h surface)
1132 _tbm_surf_queue_mutex_lock();
1134 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1135 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1136 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1137 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1139 pthread_mutex_lock(&surface_queue->lock);
1141 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1143 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1144 if (node == NULL || queue_type != NODE_LIST) {
1145 TBM_LOG_E("tbm_surface_queue_cancel_dequeue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1147 pthread_mutex_unlock(&surface_queue->lock);
1149 _tbm_surf_queue_mutex_unlock();
1150 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1153 if (node->delete_pending) {
1154 TBM_QUEUE_TRACE("delete pending tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1156 _queue_delete_node(surface_queue, node);
1158 pthread_mutex_unlock(&surface_queue->lock);
1160 _tbm_surf_queue_mutex_unlock();
1162 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1164 return TBM_SURFACE_QUEUE_ERROR_NONE;
1167 if (surface_queue->queue_size < surface_queue->num_attached) {
1168 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1170 if (surface_queue->impl && surface_queue->impl->need_detach)
1171 surface_queue->impl->need_detach(surface_queue, node);
1173 _tbm_surface_queue_detach(surface_queue, surface);
1175 pthread_mutex_unlock(&surface_queue->lock);
1177 _tbm_surf_queue_mutex_unlock();
1179 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1181 return TBM_SURFACE_QUEUE_ERROR_NONE;
1184 if (surface_queue->impl && surface_queue->impl->release)
1185 surface_queue->impl->release(surface_queue, node);
1187 _tbm_surface_queue_release(surface_queue, node, 1);
1189 if (_queue_is_empty(&surface_queue->free_queue)) {
1190 pthread_mutex_unlock(&surface_queue->lock);
1192 TBM_LOG_E("surface_queue->free_queue is empty.\n");
1193 _tbm_surf_queue_mutex_unlock();
1194 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
1197 node->type = QUEUE_NODE_TYPE_RELEASE;
1199 pthread_mutex_unlock(&surface_queue->lock);
1200 pthread_cond_signal(&surface_queue->free_cond);
1202 _tbm_surf_queue_mutex_unlock();
1204 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_DEQUEUE);
1206 return TBM_SURFACE_QUEUE_ERROR_NONE;
1209 tbm_surface_queue_error_e
1210 tbm_surface_queue_dequeue(tbm_surface_queue_h
1211 surface_queue, tbm_surface_h *surface)
1215 _tbm_surf_queue_mutex_lock();
1217 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1218 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1219 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1220 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1224 pthread_mutex_lock(&surface_queue->lock);
1226 if (_queue_is_empty(&surface_queue->free_queue)) {
1227 if (surface_queue->impl && surface_queue->impl->need_attach)
1228 surface_queue->impl->need_attach(surface_queue);
1230 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1231 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1232 pthread_mutex_unlock(&surface_queue->lock);
1233 _tbm_surf_queue_mutex_unlock();
1234 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
1238 if (surface_queue->impl && surface_queue->impl->dequeue)
1239 node = surface_queue->impl->dequeue(surface_queue);
1241 node = _tbm_surface_queue_dequeue(surface_queue);
1243 if (node == NULL || node->surface == NULL) {
1244 TBM_LOG_E("_queue_node_pop_front failed\n");
1245 pthread_mutex_unlock(&surface_queue->lock);
1247 _tbm_surf_queue_mutex_unlock();
1248 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1251 node->type = QUEUE_NODE_TYPE_DEQUEUE;
1252 *surface = node->surface;
1254 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1256 pthread_mutex_unlock(&surface_queue->lock);
1258 _tbm_surf_queue_mutex_unlock();
1260 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
1262 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
1264 return TBM_SURFACE_QUEUE_ERROR_NONE;
1268 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
1270 _tbm_surf_queue_mutex_lock();
1272 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1274 _tbm_surf_queue_mutex_unlock();
1276 _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
1278 _tbm_surf_queue_mutex_lock();
1280 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1282 pthread_mutex_lock(&surface_queue->lock);
1284 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1286 if (_queue_is_empty(&surface_queue->free_queue)) {
1287 if (surface_queue->impl && surface_queue->impl->need_attach)
1288 surface_queue->impl->need_attach(surface_queue);
1290 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1291 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1292 pthread_mutex_unlock(&surface_queue->lock);
1293 _tbm_surf_queue_mutex_unlock();
1298 if (!_queue_is_empty(&surface_queue->free_queue)) {
1299 pthread_mutex_unlock(&surface_queue->lock);
1300 _tbm_surf_queue_mutex_unlock();
1304 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1305 QUEUE_NODE_TYPE_ACQUIRE)) {
1306 _tbm_surf_queue_mutex_unlock();
1307 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
1308 _tbm_surf_queue_mutex_lock();
1310 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1311 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1312 pthread_mutex_unlock(&surface_queue->lock);
1313 _tbm_surf_queue_mutex_unlock();
1317 pthread_mutex_unlock(&surface_queue->lock);
1318 _tbm_surf_queue_mutex_unlock();
1322 pthread_mutex_unlock(&surface_queue->lock);
1323 _tbm_surf_queue_mutex_unlock();
1327 tbm_surface_queue_error_e
1328 tbm_surface_queue_release(tbm_surface_queue_h
1329 surface_queue, tbm_surface_h surface)
1334 _tbm_surf_queue_mutex_lock();
1336 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1337 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1338 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1339 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1341 pthread_mutex_lock(&surface_queue->lock);
1343 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1345 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1346 if (node == NULL || queue_type != NODE_LIST) {
1347 TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1349 pthread_mutex_unlock(&surface_queue->lock);
1351 _tbm_surf_queue_mutex_unlock();
1354 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1356 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1359 if (node->delete_pending) {
1360 TBM_QUEUE_TRACE("delete pending tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1362 _queue_delete_node(surface_queue, node);
1364 pthread_mutex_unlock(&surface_queue->lock);
1366 _tbm_surf_queue_mutex_unlock();
1368 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1370 return TBM_SURFACE_QUEUE_ERROR_NONE;
1373 if (surface_queue->queue_size < surface_queue->num_attached) {
1374 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1376 if (surface_queue->impl && surface_queue->impl->need_detach)
1377 surface_queue->impl->need_detach(surface_queue, node);
1379 _tbm_surface_queue_detach(surface_queue, surface);
1381 pthread_mutex_unlock(&surface_queue->lock);
1383 _tbm_surf_queue_mutex_unlock();
1385 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1387 return TBM_SURFACE_QUEUE_ERROR_NONE;
1390 if (surface_queue->impl && surface_queue->impl->release)
1391 surface_queue->impl->release(surface_queue, node);
1393 _tbm_surface_queue_release(surface_queue, node, 1);
1395 if (!_queue_get_node(surface_queue, FREE_QUEUE, surface, NULL)) {
1396 TBM_LOG_E("release surface(%p) but surface isn't present in the free_queue\n", surface);
1397 pthread_mutex_unlock(&surface_queue->lock);
1399 _tbm_surf_queue_mutex_unlock();
1400 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1403 node->type = QUEUE_NODE_TYPE_RELEASE;
1405 pthread_mutex_unlock(&surface_queue->lock);
1406 pthread_cond_signal(&surface_queue->free_cond);
1408 _tbm_surf_queue_mutex_unlock();
1410 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
1412 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
1414 return TBM_SURFACE_QUEUE_ERROR_NONE;
1417 tbm_surface_queue_error_e
1418 tbm_surface_queue_cancel_acquire(tbm_surface_queue_h
1419 surface_queue, tbm_surface_h surface)
1424 _tbm_surf_queue_mutex_lock();
1426 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1427 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1428 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1429 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1431 pthread_mutex_lock(&surface_queue->lock);
1433 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
1435 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
1436 if (node == NULL || queue_type != NODE_LIST) {
1437 TBM_LOG_E("tbm_surface_queue_cancel_acquire::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n",
1439 pthread_mutex_unlock(&surface_queue->lock);
1441 _tbm_surf_queue_mutex_unlock();
1442 return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
1445 if (surface_queue->impl && surface_queue->impl->enqueue)
1446 surface_queue->impl->enqueue(surface_queue, node);
1448 _tbm_surface_queue_enqueue(surface_queue, node, 1);
1450 if (_queue_is_empty(&surface_queue->dirty_queue)) {
1451 TBM_LOG_E("enqueue surface but queue is empty node:%p\n", node);
1452 pthread_mutex_unlock(&surface_queue->lock);
1454 _tbm_surf_queue_mutex_unlock();
1455 return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
1458 node->type = QUEUE_NODE_TYPE_ENQUEUE;
1460 pthread_mutex_unlock(&surface_queue->lock);
1461 pthread_cond_signal(&surface_queue->dirty_cond);
1463 _tbm_surf_queue_mutex_unlock();
1465 _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_CANCEL_ACQUIRE);
1467 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
1469 return TBM_SURFACE_QUEUE_ERROR_NONE;
1472 tbm_surface_queue_error_e
1473 tbm_surface_queue_acquire(tbm_surface_queue_h
1474 surface_queue, tbm_surface_h *surface)
1478 _tbm_surf_queue_mutex_lock();
1482 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1483 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1484 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL,
1485 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
1487 pthread_mutex_lock(&surface_queue->lock);
1489 if (surface_queue->impl && surface_queue->impl->acquire)
1490 node = surface_queue->impl->acquire(surface_queue);
1492 node = _tbm_surface_queue_acquire(surface_queue);
1494 if (node == NULL || node->surface == NULL) {
1495 TBM_LOG_E("_queue_node_pop_front failed\n");
1496 pthread_mutex_unlock(&surface_queue->lock);
1498 _tbm_surf_queue_mutex_unlock();
1499 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
1502 node->type = QUEUE_NODE_TYPE_ACQUIRE;
1504 *surface = node->surface;
1506 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
1508 pthread_mutex_unlock(&surface_queue->lock);
1510 _tbm_surf_queue_mutex_unlock();
1513 tbm_surface_internal_dump_buffer(*surface, "acquire");
1515 _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
1517 return TBM_SURFACE_QUEUE_ERROR_NONE;
1521 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
1523 _tbm_surf_queue_mutex_lock();
1525 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
1527 pthread_mutex_lock(&surface_queue->lock);
1529 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1531 if (!_queue_is_empty(&surface_queue->dirty_queue)) {
1532 pthread_mutex_unlock(&surface_queue->lock);
1533 _tbm_surf_queue_mutex_unlock();
1537 if (wait && _tbm_surface_queue_get_node_count(surface_queue,
1538 QUEUE_NODE_TYPE_DEQUEUE)) {
1539 _tbm_surf_queue_mutex_unlock();
1540 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
1541 _tbm_surf_queue_mutex_lock();
1543 if (!_tbm_surface_queue_is_valid(surface_queue)) {
1544 TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
1545 pthread_mutex_unlock(&surface_queue->lock);
1546 _tbm_surf_queue_mutex_unlock();
1550 pthread_mutex_unlock(&surface_queue->lock);
1551 _tbm_surf_queue_mutex_unlock();
1555 pthread_mutex_unlock(&surface_queue->lock);
1556 _tbm_surf_queue_mutex_unlock();
1561 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
1563 queue_node *node = NULL, *tmp;
1565 _tbm_surf_queue_mutex_lock();
1567 TBM_SURF_QUEUE_RETURN_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue));
1569 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1571 LIST_DEL(&surface_queue->item_link);
1573 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1574 _queue_delete_node(surface_queue, node);
1576 if (surface_queue->impl && surface_queue->impl->destroy)
1577 surface_queue->impl->destroy(surface_queue);
1579 _notify_emit(surface_queue, &surface_queue->destory_noti);
1581 _notify_remove_all(&surface_queue->destory_noti);
1582 _notify_remove_all(&surface_queue->dequeuable_noti);
1583 _notify_remove_all(&surface_queue->dequeue_noti);
1584 _notify_remove_all(&surface_queue->can_dequeue_noti);
1585 _notify_remove_all(&surface_queue->acquirable_noti);
1586 _notify_remove_all(&surface_queue->reset_noti);
1587 _trace_remove_all(&surface_queue->trace_noti);
1589 pthread_mutex_destroy(&surface_queue->lock);
1591 free(surface_queue);
1593 if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list))
1594 _deinit_tbm_surf_queue_bufmgr();
1596 _tbm_surf_queue_mutex_unlock();
1599 tbm_surface_queue_error_e
1600 tbm_surface_queue_reset(tbm_surface_queue_h
1601 surface_queue, int width, int height, int format)
1603 queue_node *node = NULL, *tmp;
1605 _tbm_surf_queue_mutex_lock();
1607 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1608 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1610 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1612 if (width == surface_queue->width && height == surface_queue->height &&
1613 format == surface_queue->format) {
1614 _tbm_surf_queue_mutex_unlock();
1615 return TBM_SURFACE_QUEUE_ERROR_NONE;
1618 pthread_mutex_lock(&surface_queue->lock);
1620 surface_queue->width = width;
1621 surface_queue->height = height;
1622 surface_queue->format = format;
1624 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1625 /* Destory surface and Push to free_queue */
1626 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1627 _queue_delete_node(surface_queue, node);
1629 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1630 node->delete_pending = 1;
1632 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1633 _queue_delete_node(surface_queue, node);
1635 _queue_init(&surface_queue->dirty_queue);
1636 LIST_INITHEAD(&surface_queue->list);
1640 _queue_init(&surface_queue->free_queue);
1642 surface_queue->num_attached = 0;
1644 if (surface_queue->impl && surface_queue->impl->reset)
1645 surface_queue->impl->reset(surface_queue);
1647 pthread_mutex_unlock(&surface_queue->lock);
1648 pthread_cond_signal(&surface_queue->free_cond);
1650 _tbm_surf_queue_mutex_unlock();
1652 _notify_emit(surface_queue, &surface_queue->reset_noti);
1654 return TBM_SURFACE_QUEUE_ERROR_NONE;
1657 tbm_surface_queue_error_e
1658 tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
1660 _tbm_surf_queue_mutex_lock();
1662 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1663 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1665 _tbm_surf_queue_mutex_unlock();
1667 _notify_emit(surface_queue, &surface_queue->reset_noti);
1669 return TBM_SURFACE_QUEUE_ERROR_NONE;
1672 tbm_surface_queue_error_e
1673 tbm_surface_queue_set_size(tbm_surface_queue_h
1674 surface_queue, int queue_size, int flush)
1676 queue_node *node = NULL, *tmp;
1678 _tbm_surf_queue_mutex_lock();
1680 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1681 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1682 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(queue_size > 0,
1683 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1685 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1687 if ((surface_queue->queue_size == queue_size) && !flush) {
1688 _tbm_surf_queue_mutex_unlock();
1689 return TBM_SURFACE_QUEUE_ERROR_NONE;
1692 pthread_mutex_lock(&surface_queue->lock);
1695 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1696 /* Destory surface and Push to free_queue */
1697 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1698 _queue_delete_node(surface_queue, node);
1700 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1701 node->delete_pending = 1;
1703 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1704 _queue_delete_node(surface_queue, node);
1706 _queue_init(&surface_queue->dirty_queue);
1707 LIST_INITHEAD(&surface_queue->list);
1711 _queue_init(&surface_queue->free_queue);
1713 surface_queue->num_attached = 0;
1714 surface_queue->queue_size = queue_size;
1716 if (surface_queue->impl && surface_queue->impl->reset)
1717 surface_queue->impl->reset(surface_queue);
1719 pthread_mutex_unlock(&surface_queue->lock);
1720 pthread_cond_signal(&surface_queue->free_cond);
1722 _tbm_surf_queue_mutex_unlock();
1724 _notify_emit(surface_queue, &surface_queue->reset_noti);
1726 return TBM_SURFACE_QUEUE_ERROR_NONE;
1728 if (surface_queue->queue_size > queue_size) {
1729 int need_del = surface_queue->queue_size - queue_size;
1731 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
1732 TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
1734 if (surface_queue->impl && surface_queue->impl->need_detach)
1735 surface_queue->impl->need_detach(surface_queue, node);
1737 _tbm_surface_queue_detach(surface_queue, node->surface);
1745 surface_queue->queue_size = queue_size;
1747 pthread_mutex_unlock(&surface_queue->lock);
1749 _tbm_surf_queue_mutex_unlock();
1751 return TBM_SURFACE_QUEUE_ERROR_NONE;
1755 tbm_surface_queue_error_e
1756 tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
1758 queue_node *node = NULL;
1760 _tbm_surf_queue_mutex_lock();
1762 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1763 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1765 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1767 if (surface_queue->num_attached == 0) {
1768 _tbm_surf_queue_mutex_unlock();
1769 return TBM_SURFACE_QUEUE_ERROR_NONE;
1772 pthread_mutex_lock(&surface_queue->lock);
1774 /* Destory surface in free_queue */
1775 while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
1776 if (surface_queue->impl && surface_queue->impl->need_detach)
1777 surface_queue->impl->need_detach(surface_queue, node);
1779 _tbm_surface_queue_detach(surface_queue, node->surface);
1783 _queue_init(&surface_queue->free_queue);
1785 pthread_mutex_unlock(&surface_queue->lock);
1786 _tbm_surf_queue_mutex_unlock();
1788 return TBM_SURFACE_QUEUE_ERROR_NONE;
1791 tbm_surface_queue_error_e
1792 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1794 queue_node *node = NULL, *tmp;
1796 _tbm_surf_queue_mutex_lock();
1798 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1799 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1801 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1803 if (surface_queue->num_attached == 0) {
1804 _tbm_surf_queue_mutex_unlock();
1805 return TBM_SURFACE_QUEUE_ERROR_NONE;
1808 pthread_mutex_lock(&surface_queue->lock);
1810 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) {
1811 /* Destory surface and Push to free_queue */
1812 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link)
1813 _queue_delete_node(surface_queue, node);
1815 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link)
1816 node->delete_pending = 1;
1818 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
1819 _queue_delete_node(surface_queue, node);
1821 _queue_init(&surface_queue->dirty_queue);
1822 LIST_INITHEAD(&surface_queue->list);
1826 _queue_init(&surface_queue->free_queue);
1828 surface_queue->num_attached = 0;
1830 if (surface_queue->impl && surface_queue->impl->reset)
1831 surface_queue->impl->reset(surface_queue);
1833 pthread_mutex_unlock(&surface_queue->lock);
1834 pthread_cond_signal(&surface_queue->free_cond);
1836 _tbm_surf_queue_mutex_unlock();
1838 _notify_emit(surface_queue, &surface_queue->reset_noti);
1840 return TBM_SURFACE_QUEUE_ERROR_NONE;
1843 tbm_surface_queue_error_e
1844 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1845 tbm_surface_h *surfaces, int *num)
1847 queue_node *node = NULL;
1849 _tbm_surf_queue_mutex_lock();
1851 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1852 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1853 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1854 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1858 pthread_mutex_lock(&surface_queue->lock);
1860 LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) {
1862 surfaces[*num] = node->surface;
1867 pthread_mutex_unlock(&surface_queue->lock);
1869 _tbm_surf_queue_mutex_unlock();
1871 return TBM_SURFACE_QUEUE_ERROR_NONE;
1874 tbm_surface_queue_error_e
1875 tbm_surface_queue_get_trace_surface_num(
1876 tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
1878 _tbm_surf_queue_mutex_lock();
1880 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
1881 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1882 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
1883 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1887 pthread_mutex_lock(&surface_queue->lock);
1890 case TBM_SURFACE_QUEUE_TRACE_NONE:
1893 case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
1894 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
1896 case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
1897 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
1899 case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
1900 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
1902 case TBM_SURFACE_QUEUE_TRACE_RELEASE:
1903 *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
1909 pthread_mutex_unlock(&surface_queue->lock);
1911 _tbm_surf_queue_mutex_unlock();
1913 return TBM_SURFACE_QUEUE_ERROR_NONE;
1918 } tbm_queue_default;
1921 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1923 free(surface_queue->impl_data);
1927 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1929 tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
1930 tbm_surface_h surface;
1932 if (surface_queue->queue_size == surface_queue->num_attached)
1935 if (surface_queue->alloc_cb) {
1936 pthread_mutex_unlock(&surface_queue->lock);
1937 _tbm_surf_queue_mutex_unlock();
1938 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1939 _tbm_surf_queue_mutex_lock();
1940 pthread_mutex_lock(&surface_queue->lock);
1946 tbm_surface_internal_ref(surface);
1948 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1949 surface_queue->height,
1950 surface_queue->format,
1952 TBM_RETURN_IF_FAIL(surface != NULL);
1955 _tbm_surface_queue_attach(surface_queue, surface);
1956 tbm_surface_internal_unref(surface);
1959 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1960 NULL, /*__tbm_queue_default_init*/
1961 NULL, /*__tbm_queue_default_reset*/
1962 __tbm_queue_default_destroy,
1963 __tbm_queue_default_need_attach,
1964 NULL, /*__tbm_queue_default_enqueue*/
1965 NULL, /*__tbm_queue_default_release*/
1966 NULL, /*__tbm_queue_default_dequeue*/
1967 NULL, /*__tbm_queue_default_acquire*/
1968 NULL, /*__tbm_queue_default_need_detach*/
1972 tbm_surface_queue_create(int queue_size, int width,
1973 int height, int format, int flags)
1975 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1976 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1977 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1978 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1980 _tbm_surf_queue_mutex_lock();
1982 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1983 sizeof(struct _tbm_surface_queue));
1984 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1986 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1988 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1989 sizeof(tbm_queue_default));
1991 TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
1992 free(surface_queue);
1993 _tbm_surf_queue_mutex_unlock();
1997 data->flags = flags;
1998 _tbm_surface_queue_init(surface_queue,
2000 width, height, format,
2001 &tbm_queue_default_impl, data);
2003 _tbm_surf_queue_mutex_unlock();
2005 return surface_queue;
2011 } tbm_queue_sequence;
2014 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
2016 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2018 _queue_init(&data->dequeue_list);
2022 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
2024 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2026 if (surface_queue->modes & TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE)
2029 _queue_init(&data->dequeue_list);
2033 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
2035 free(surface_queue->impl_data);
2039 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
2041 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2042 tbm_surface_h surface;
2044 if (surface_queue->queue_size == surface_queue->num_attached)
2047 if (surface_queue->alloc_cb) {
2048 pthread_mutex_unlock(&surface_queue->lock);
2049 _tbm_surf_queue_mutex_unlock();
2050 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
2051 _tbm_surf_queue_mutex_lock();
2052 pthread_mutex_lock(&surface_queue->lock);
2058 tbm_surface_internal_ref(surface);
2060 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
2061 surface_queue->height,
2062 surface_queue->format,
2064 TBM_RETURN_IF_FAIL(surface != NULL);
2067 _tbm_surface_queue_attach(surface_queue, surface);
2068 tbm_surface_internal_unref(surface);
2072 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
2075 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2076 queue_node *first = NULL;
2078 first = container_of(data->dequeue_list.head.next, first, item_link);
2079 if (first != node) {
2083 node->priv_flags = 0;
2085 _queue_node_pop(&data->dequeue_list, node);
2086 _tbm_surface_queue_enqueue(surface_queue, node, 1);
2090 __tbm_queue_sequence_release(tbm_surface_queue_h surface_queue,
2093 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2095 if (node->priv_flags) {
2096 node->priv_flags = 0;
2097 _queue_node_pop(&data->dequeue_list, node);
2100 _tbm_surface_queue_release(surface_queue, node, 1);
2104 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
2107 tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
2110 node = _tbm_surface_queue_dequeue(surface_queue);
2112 _queue_node_push_back(&data->dequeue_list, node);
2113 node->priv_flags = 1;
2119 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
2120 __tbm_queue_sequence_init,
2121 __tbm_queue_sequence_reset,
2122 __tbm_queue_sequence_destroy,
2123 __tbm_queue_sequence_need_attach,
2124 __tbm_queue_sequence_enqueue,
2125 __tbm_queue_sequence_release,
2126 __tbm_queue_sequence_dequeue,
2127 NULL, /*__tbm_queue_sequence_acquire*/
2128 NULL, /*__tbm_queue_sequence_need_dettach*/
2132 tbm_surface_queue_sequence_create(int queue_size, int width,
2133 int height, int format, int flags)
2135 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
2136 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
2137 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
2138 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
2140 _tbm_surf_queue_mutex_lock();
2142 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
2143 sizeof(struct _tbm_surface_queue));
2144 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
2146 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
2148 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
2149 sizeof(tbm_queue_sequence));
2151 TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
2152 free(surface_queue);
2153 _tbm_surf_queue_mutex_unlock();
2157 data->flags = flags;
2158 _tbm_surface_queue_init(surface_queue,
2160 width, height, format,
2161 &tbm_queue_sequence_impl, data);
2163 _tbm_surf_queue_mutex_unlock();
2165 return surface_queue;
2168 tbm_surface_queue_error_e
2169 tbm_surface_queue_set_modes(tbm_surface_queue_h surface_queue,
2172 _tbm_surf_queue_mutex_lock();
2174 TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
2175 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
2177 pthread_mutex_lock(&surface_queue->lock);
2179 if (modes == TBM_SURFACE_QUEUE_MODE_NONE)
2180 modes = TBM_SURFACE_QUEUE_MODE_NONE;
2182 surface_queue->modes |= modes;
2184 pthread_mutex_unlock(&surface_queue->lock);
2186 _tbm_surf_queue_mutex_unlock();
2188 return TBM_SURFACE_QUEUE_ERROR_NONE;