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"
42 #define TBM_QUEUE_TRACE() TBM_LOG("[QUEUE_TRACE] %s:%d surface_queue:%p\n", __func__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
46 #define TBM_QUEUE_TRACE()
52 struct list_head head;
53 struct list_head tail;
59 tbm_surface_h surface;
61 struct list_head item_link;
62 struct list_head link;
64 unsigned int priv_flags; /*for each queue*/
68 struct list_head link;
70 tbm_surface_queue_notify_cb cb;
74 typedef struct _tbm_surface_queue_interface {
75 void (*init)(tbm_surface_queue_h queue);
76 void (*reset)(tbm_surface_queue_h queue);
77 void (*destroy)(tbm_surface_queue_h queue);
78 void (*need_attach)(tbm_surface_queue_h queue);
80 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
81 void (*release)(tbm_surface_queue_h queue, queue_node *node);
82 queue_node *(*dequeue)(tbm_surface_queue_h queue);
83 queue_node *(*acquire)(tbm_surface_queue_h queue);
84 } tbm_surface_queue_interface;
86 struct _tbm_surface_queue {
94 struct list_head list;
96 struct list_head destory_noti;
97 struct list_head dequeuable_noti;
98 struct list_head acquirable_noti;
99 struct list_head reset_noti;
101 tbm_surface_queue_notify_cb destroy_cb;
102 void *destroy_cb_data;
104 tbm_surface_queue_notify_cb dequeuable_cb;
105 void *dequeuable_cb_data;
107 tbm_surface_queue_notify_cb acquirable_cb;
108 void *acquirable_cb_data;
110 tbm_surface_queue_notify_cb reset_cb;
113 pthread_mutex_t lock;
114 pthread_cond_t free_cond;
115 pthread_cond_t dirty_cond;
117 const tbm_surface_queue_interface *impl;
120 //For external buffer allocation
121 tbm_surface_alloc_cb alloc_cb;
122 tbm_surface_free_cb free_cb;
127 _queue_node_create(void)
129 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
131 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
137 _queue_node_delete(queue_node *node)
139 LIST_DEL(&node->item_link);
140 LIST_DEL(&node->link);
145 _queue_is_empty(queue *queue)
147 if (queue->head.next == &queue->tail)
154 _queue_node_push_back(queue *queue, queue_node *node)
156 LIST_ADDTAIL(&node->item_link, &queue->tail);
161 _queue_node_push_front(queue *queue, queue_node *node)
163 LIST_ADD(&node->item_link, &queue->head);
168 _queue_node_pop_front(queue *queue)
170 queue_node *node = NULL;
172 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
174 LIST_DEL(&node->item_link);
181 _queue_node_pop(queue *queue, queue_node *node)
183 LIST_DEL(&node->item_link);
190 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
191 tbm_surface_h surface, int *out_type)
193 queue_node *node = NULL;
194 queue_node *tmp = NULL;
197 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
201 if (type & FREE_QUEUE) {
202 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
204 if (node->surface == surface) {
206 *out_type = FREE_QUEUE;
213 if (type & DIRTY_QUEUE) {
214 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
216 if (node->surface == surface) {
218 *out_type = DIRTY_QUEUE;
225 if (type & NODE_LIST) {
226 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
227 if (node->surface == surface) {
229 *out_type = NODE_LIST;
240 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
243 if (surface_queue->free_cb) {
244 surface_queue->free_cb(surface_queue,
245 surface_queue->alloc_cb_data,
249 tbm_surface_destroy(node->surface);
252 _queue_node_delete(node);
256 _queue_init(queue *queue)
258 LIST_INITHEAD(&queue->head);
259 LIST_INITHEAD(&queue->tail);
260 LIST_ADDTAIL(&queue->head, &queue->tail);
265 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
268 TBM_RETURN_IF_FAIL(cb != NULL);
270 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
272 TBM_RETURN_IF_FAIL(item != NULL);
274 LIST_INITHEAD(&item->link);
278 LIST_ADDTAIL(&item->link, list);
282 _notify_remove(struct list_head *list,
283 tbm_surface_queue_notify_cb cb, void *data)
285 queue_notify *item = NULL, *tmp = NULL;
287 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
288 if (item->cb == cb && item->data == data) {
289 LIST_DEL(&item->link);
295 TBM_LOG("Cannot find notifiy\n");
299 _notify_remove_all(struct list_head *list)
301 queue_notify *item = NULL, *tmp = NULL;
303 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
304 LIST_DEL(&item->link);
310 _notify_emit(tbm_surface_queue_h surface_queue,
311 struct list_head *list)
313 queue_notify *item = NULL, *tmp = NULL;
315 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
316 item->cb(surface_queue, item->data);
321 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
322 tbm_surface_h surface)
324 queue_node *node = NULL;
326 node = _queue_node_create();
327 TBM_RETURN_IF_FAIL(node != NULL);
329 tbm_surface_internal_ref(surface);
330 node->surface = surface;
332 LIST_ADDTAIL(&node->link, &surface_queue->list);
333 _queue_node_push_back(&surface_queue->free_queue, node);
337 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
338 tbm_surface_h surface)
340 queue_node *node = NULL;
343 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
345 _queue_delete_node(surface_queue, node);
349 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
350 queue_node *node, int push_back)
353 _queue_node_push_back(&surface_queue->dirty_queue, node);
355 _queue_node_push_front(&surface_queue->dirty_queue, node);
359 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
361 queue_node *node = NULL;
363 if (_queue_is_empty(&surface_queue->free_queue)) {
364 if (surface_queue->impl && surface_queue->impl->need_attach)
365 surface_queue->impl->need_attach(surface_queue);
367 if (_queue_is_empty(&surface_queue->free_queue))
371 node = _queue_node_pop_front(&surface_queue->free_queue);
377 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
379 queue_node *node = NULL;
381 if (_queue_is_empty(&surface_queue->dirty_queue))
384 node = _queue_node_pop_front(&surface_queue->dirty_queue);
390 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
391 queue_node *node, int push_back)
394 _queue_node_push_back(&surface_queue->free_queue, node);
396 _queue_node_push_front(&surface_queue->free_queue, node);
400 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
402 int width, int height, int format,
403 const tbm_surface_queue_interface *impl, void *data)
405 TBM_RETURN_IF_FAIL(surface_queue != NULL);
406 TBM_RETURN_IF_FAIL(impl != NULL);
408 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
410 pthread_mutex_init(&surface_queue->lock, NULL);
411 pthread_cond_init(&surface_queue->free_cond, NULL);
412 pthread_cond_init(&surface_queue->dirty_cond, NULL);
414 surface_queue->queue_size = queue_size;
415 surface_queue->width = width;
416 surface_queue->height = height;
417 surface_queue->format = format;
418 surface_queue->impl = impl;
419 surface_queue->impl_data = data;
421 _queue_init(&surface_queue->free_queue);
422 _queue_init(&surface_queue->dirty_queue);
423 LIST_INITHEAD(&surface_queue->list);
425 LIST_INITHEAD(&surface_queue->destory_noti);
426 LIST_INITHEAD(&surface_queue->acquirable_noti);
427 LIST_INITHEAD(&surface_queue->dequeuable_noti);
428 LIST_INITHEAD(&surface_queue->reset_noti);
430 if (surface_queue->impl && surface_queue->impl->init)
431 surface_queue->impl->init(surface_queue);
434 tbm_surface_queue_error_e
435 tbm_surface_queue_set_destroy_cb(
436 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
439 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
440 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
442 pthread_mutex_lock(&surface_queue->lock);
446 surface_queue->destroy_cb = destroy_cb;
447 surface_queue->destroy_cb_data = data;
449 pthread_mutex_unlock(&surface_queue->lock);
451 return TBM_SURFACE_QUEUE_ERROR_NONE;
454 tbm_surface_queue_error_e
455 tbm_surface_queue_add_destroy_cb(
456 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
459 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
460 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
462 pthread_mutex_lock(&surface_queue->lock);
466 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
468 pthread_mutex_unlock(&surface_queue->lock);
470 return TBM_SURFACE_QUEUE_ERROR_NONE;
473 tbm_surface_queue_error_e
474 tbm_surface_queue_remove_destroy_cb(
475 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
478 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
479 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
481 pthread_mutex_lock(&surface_queue->lock);
485 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
487 pthread_mutex_unlock(&surface_queue->lock);
489 return TBM_SURFACE_QUEUE_ERROR_NONE;
492 tbm_surface_queue_error_e
493 tbm_surface_queue_set_dequeuable_cb(
494 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
497 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
498 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
500 pthread_mutex_lock(&surface_queue->lock);
504 surface_queue->dequeuable_cb = dequeuable_cb;
505 surface_queue->dequeuable_cb_data = data;
507 pthread_mutex_unlock(&surface_queue->lock);
509 return TBM_SURFACE_QUEUE_ERROR_NONE;
512 tbm_surface_queue_error_e
513 tbm_surface_queue_add_dequeuable_cb(
514 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
517 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
518 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
520 pthread_mutex_lock(&surface_queue->lock);
524 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
526 pthread_mutex_unlock(&surface_queue->lock);
528 return TBM_SURFACE_QUEUE_ERROR_NONE;
531 tbm_surface_queue_error_e
532 tbm_surface_queue_remove_dequeuable_cb(
533 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
536 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
537 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
539 pthread_mutex_lock(&surface_queue->lock);
543 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
545 pthread_mutex_unlock(&surface_queue->lock);
547 return TBM_SURFACE_QUEUE_ERROR_NONE;
550 tbm_surface_queue_error_e
551 tbm_surface_queue_set_acquirable_cb(
552 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
555 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
556 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
558 pthread_mutex_lock(&surface_queue->lock);
562 surface_queue->acquirable_cb = acquirable_cb;
563 surface_queue->acquirable_cb_data = data;
565 pthread_mutex_unlock(&surface_queue->lock);
567 return TBM_SURFACE_QUEUE_ERROR_NONE;
570 tbm_surface_queue_error_e
571 tbm_surface_queue_add_acquirable_cb(
572 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
575 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
576 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
578 pthread_mutex_lock(&surface_queue->lock);
582 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
584 pthread_mutex_unlock(&surface_queue->lock);
586 return TBM_SURFACE_QUEUE_ERROR_NONE;
589 tbm_surface_queue_error_e
590 tbm_surface_queue_remove_acquirable_cb(
591 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
594 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
595 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
597 pthread_mutex_lock(&surface_queue->lock);
601 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
603 pthread_mutex_unlock(&surface_queue->lock);
605 return TBM_SURFACE_QUEUE_ERROR_NONE;
608 tbm_surface_queue_error_e
609 tbm_surface_queue_set_alloc_cb(
610 tbm_surface_queue_h surface_queue,
611 tbm_surface_alloc_cb alloc_cb,
612 tbm_surface_free_cb free_cb,
615 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
616 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
618 pthread_mutex_lock(&surface_queue->lock);
622 surface_queue->alloc_cb = alloc_cb;
623 surface_queue->free_cb = free_cb;
624 surface_queue->alloc_cb_data = data;
626 pthread_mutex_unlock(&surface_queue->lock);
628 return TBM_SURFACE_QUEUE_ERROR_NONE;
632 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
634 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
638 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
640 return surface_queue->width;
644 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
646 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
650 return surface_queue->height;
654 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
656 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
660 return surface_queue->format;
664 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
666 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
670 return surface_queue->queue_size;
673 tbm_surface_queue_error_e
674 tbm_surface_queue_set_reset_cb(
675 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
678 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
679 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
681 pthread_mutex_lock(&surface_queue->lock);
685 surface_queue->reset_cb = reset_cb;
686 surface_queue->reset_cb_data = data;
688 pthread_mutex_unlock(&surface_queue->lock);
690 return TBM_SURFACE_QUEUE_ERROR_NONE;
693 tbm_surface_queue_error_e
694 tbm_surface_queue_add_reset_cb(
695 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
698 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
699 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
701 pthread_mutex_lock(&surface_queue->lock);
705 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
707 pthread_mutex_unlock(&surface_queue->lock);
709 return TBM_SURFACE_QUEUE_ERROR_NONE;
712 tbm_surface_queue_error_e
713 tbm_surface_queue_remove_reset_cb(
714 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
717 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
718 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
720 pthread_mutex_lock(&surface_queue->lock);
724 _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
726 pthread_mutex_unlock(&surface_queue->lock);
728 return TBM_SURFACE_QUEUE_ERROR_NONE;
731 tbm_surface_queue_error_e
732 tbm_surface_queue_enqueue(tbm_surface_queue_h
733 surface_queue, tbm_surface_h surface)
735 queue_node *node = NULL;
738 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
739 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
740 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
741 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
743 pthread_mutex_lock(&surface_queue->lock);
747 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
748 if (node == NULL || queue_type != NODE_LIST) {
749 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
751 pthread_mutex_unlock(&surface_queue->lock);
752 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
755 if (surface_queue->impl && surface_queue->impl->enqueue)
756 surface_queue->impl->enqueue(surface_queue, node);
758 _tbm_surface_queue_enqueue(surface_queue, node, 1);
760 if (_queue_is_empty(&surface_queue->dirty_queue)) {
761 pthread_mutex_unlock(&surface_queue->lock);
762 return TBM_SURFACE_QUEUE_ERROR_NONE;
765 pthread_mutex_unlock(&surface_queue->lock);
766 pthread_cond_signal(&surface_queue->dirty_cond);
768 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
769 if (surface_queue->acquirable_cb)
770 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
772 return TBM_SURFACE_QUEUE_ERROR_NONE;
775 tbm_surface_queue_error_e
776 tbm_surface_queue_dequeue(tbm_surface_queue_h
777 surface_queue, tbm_surface_h *surface)
779 queue_node *node = NULL;
781 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
782 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
783 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
784 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
786 pthread_mutex_lock(&surface_queue->lock);
790 if (surface_queue->impl && surface_queue->impl->dequeue)
791 node = surface_queue->impl->dequeue(surface_queue);
793 node = _tbm_surface_queue_dequeue(surface_queue);
797 pthread_mutex_unlock(&surface_queue->lock);
798 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
801 if (node->surface == NULL) {
803 TBM_LOG("_queue_node_pop_front failed\n");
804 pthread_mutex_unlock(&surface_queue->lock);
805 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
808 *surface = node->surface;
810 pthread_mutex_unlock(&surface_queue->lock);
812 return TBM_SURFACE_QUEUE_ERROR_NONE;
816 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
818 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
820 pthread_mutex_lock(&surface_queue->lock);
824 if (_queue_is_empty(&surface_queue->free_queue)) {
825 if (surface_queue->impl && surface_queue->impl->need_attach)
826 surface_queue->impl->need_attach(surface_queue);
829 if (_queue_is_empty(&surface_queue->free_queue)) {
831 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
832 pthread_mutex_unlock(&surface_queue->lock);
836 pthread_mutex_unlock(&surface_queue->lock);
840 pthread_mutex_unlock(&surface_queue->lock);
845 tbm_surface_queue_error_e
846 tbm_surface_queue_release(tbm_surface_queue_h
847 surface_queue, tbm_surface_h surface)
849 queue_node *node = NULL;
852 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
853 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
854 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
855 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
857 pthread_mutex_lock(&surface_queue->lock);
861 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
862 if (node == NULL || queue_type != NODE_LIST) {
863 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
865 pthread_mutex_unlock(&surface_queue->lock);
866 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
869 if (surface_queue->impl && surface_queue->impl->release)
870 surface_queue->impl->release(surface_queue, node);
872 _tbm_surface_queue_release(surface_queue, node, 1);
874 if (_queue_is_empty(&surface_queue->free_queue)) {
875 pthread_mutex_unlock(&surface_queue->lock);
876 return TBM_SURFACE_QUEUE_ERROR_NONE;
879 pthread_mutex_unlock(&surface_queue->lock);
880 pthread_cond_signal(&surface_queue->free_cond);
882 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
883 if (surface_queue->dequeuable_cb)
884 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
886 return TBM_SURFACE_QUEUE_ERROR_NONE;
889 tbm_surface_queue_error_e
890 tbm_surface_queue_acquire(tbm_surface_queue_h
891 surface_queue, tbm_surface_h *surface)
893 queue_node *node = NULL;
895 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
896 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
897 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
898 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
900 pthread_mutex_lock(&surface_queue->lock);
904 if (surface_queue->impl && surface_queue->impl->acquire)
905 node = surface_queue->impl->acquire(surface_queue);
907 node = _tbm_surface_queue_acquire(surface_queue);
911 pthread_mutex_unlock(&surface_queue->lock);
912 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
915 if (node->surface == NULL) {
917 TBM_LOG("_queue_node_pop_front failed\n");
918 pthread_mutex_unlock(&surface_queue->lock);
919 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
922 *surface = node->surface;
924 pthread_mutex_unlock(&surface_queue->lock);
926 return TBM_SURFACE_QUEUE_ERROR_NONE;
930 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
932 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
934 pthread_mutex_lock(&surface_queue->lock);
938 if (_queue_is_empty(&surface_queue->dirty_queue)) {
940 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
941 pthread_mutex_unlock(&surface_queue->lock);
945 pthread_mutex_unlock(&surface_queue->lock);
949 pthread_mutex_unlock(&surface_queue->lock);
955 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
957 queue_node *node = NULL, *tmp = NULL;
959 TBM_RETURN_IF_FAIL(surface_queue != NULL);
963 if (surface_queue->destroy_cb)
964 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
966 _notify_emit(surface_queue, &surface_queue->destory_noti);
968 if (surface_queue->impl && surface_queue->impl->destroy)
969 surface_queue->impl->destroy(surface_queue);
971 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
972 _queue_delete_node(surface_queue, node);
975 _notify_remove_all(&surface_queue->destory_noti);
976 _notify_remove_all(&surface_queue->acquirable_noti);
977 _notify_remove_all(&surface_queue->dequeuable_noti);
978 _notify_remove_all(&surface_queue->reset_noti);
980 pthread_mutex_destroy(&surface_queue->lock);
984 tbm_surface_queue_error_e
985 tbm_surface_queue_reset(tbm_surface_queue_h
986 surface_queue, int width, int height, int format)
988 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
989 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
993 queue_node *node = NULL, *tmp = NULL;
995 if (width == surface_queue->width && height == surface_queue->height &&
996 format == surface_queue->format)
997 return TBM_SURFACE_QUEUE_ERROR_NONE;
999 pthread_mutex_lock(&surface_queue->lock);
1001 surface_queue->width = width;
1002 surface_queue->height = height;
1003 surface_queue->format = format;
1005 /* Destory surface and Push to free_queue */
1006 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1007 _queue_delete_node(surface_queue, node);
1011 _queue_init(&surface_queue->free_queue);
1012 _queue_init(&surface_queue->dirty_queue);
1013 LIST_INITHEAD(&surface_queue->list);
1015 if (surface_queue->impl && surface_queue->impl->reset)
1016 surface_queue->impl->reset(surface_queue);
1018 pthread_mutex_unlock(&surface_queue->lock);
1019 pthread_cond_signal(&surface_queue->free_cond);
1021 _notify_emit(surface_queue, &surface_queue->reset_noti);
1022 if (surface_queue->reset_cb)
1023 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
1025 return TBM_SURFACE_QUEUE_ERROR_NONE;
1028 tbm_surface_queue_error_e
1029 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1031 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1032 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1034 queue_node *node = NULL, *tmp = NULL;
1036 pthread_mutex_lock(&surface_queue->lock);
1040 /* Destory surface and Push to free_queue */
1041 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1042 _queue_delete_node(surface_queue, node);
1046 _queue_init(&surface_queue->free_queue);
1047 _queue_init(&surface_queue->dirty_queue);
1048 LIST_INITHEAD(&surface_queue->list);
1050 if (surface_queue->impl && surface_queue->impl->reset)
1051 surface_queue->impl->reset(surface_queue);
1053 _notify_emit(surface_queue, &surface_queue->reset_noti);
1054 if (surface_queue->reset_cb)
1055 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
1057 pthread_mutex_unlock(&surface_queue->lock);
1058 pthread_cond_signal(&surface_queue->free_cond);
1060 return TBM_SURFACE_QUEUE_ERROR_NONE;
1067 } tbm_queue_default;
1070 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1072 tbm_queue_default *data = surface_queue->impl_data;
1074 data->num_attached = 0;
1078 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1080 tbm_queue_default *data = surface_queue->impl_data;
1082 data->num_attached = 0;
1086 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1088 free(surface_queue->impl_data);
1092 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1094 tbm_queue_default *data = surface_queue->impl_data;
1095 tbm_surface_h surface;
1097 if (data->queue_size == data->num_attached)
1100 if (surface_queue->alloc_cb) {
1101 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1102 TBM_RETURN_IF_FAIL(surface != NULL);
1103 tbm_surface_internal_ref(surface);
1105 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1106 surface_queue->height,
1107 surface_queue->format,
1109 TBM_RETURN_IF_FAIL(surface != NULL);
1112 _tbm_surface_queue_attach(surface_queue, surface);
1113 tbm_surface_internal_unref(surface);
1114 data->num_attached++;
1117 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1118 __tbm_queue_default_init,
1119 __tbm_queue_default_reset,
1120 __tbm_queue_default_destroy,
1121 __tbm_queue_default_need_attach,
1122 NULL, /*__tbm_queue_default_enqueue*/
1123 NULL, /*__tbm_queue_default_release*/
1124 NULL, /*__tbm_queue_default_dequeue*/
1125 NULL, /*__tbm_queue_default_acquire*/
1129 tbm_surface_queue_create(int queue_size, int width,
1130 int height, int format, int flags)
1132 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1133 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1134 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1135 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1137 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1138 sizeof(struct _tbm_surface_queue));
1139 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1143 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1144 sizeof(tbm_queue_default));
1146 free(surface_queue);
1150 data->queue_size = queue_size;
1151 data->flags = flags;
1152 _tbm_surface_queue_init(surface_queue,
1154 width, height, format,
1155 &tbm_queue_default_impl, data);
1157 return surface_queue;
1165 } tbm_queue_sequence;
1168 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1170 tbm_queue_sequence *data = surface_queue->impl_data;
1172 data->num_attached = 0;
1173 _queue_init(&data->dequeue_list);
1177 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1179 tbm_queue_sequence *data = surface_queue->impl_data;
1181 data->num_attached = 0;
1182 _queue_init(&data->dequeue_list);
1186 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1188 free(surface_queue->impl_data);
1192 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1194 tbm_queue_sequence *data = surface_queue->impl_data;
1195 tbm_surface_h surface;
1197 if (data->queue_size == data->num_attached)
1200 if (surface_queue->alloc_cb) {
1201 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1202 TBM_RETURN_IF_FAIL(surface != NULL);
1203 tbm_surface_internal_ref(surface);
1205 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1206 surface_queue->height,
1207 surface_queue->format,
1209 TBM_RETURN_IF_FAIL(surface != NULL);
1212 _tbm_surface_queue_attach(surface_queue, surface);
1213 tbm_surface_internal_unref(surface);
1214 data->num_attached++;
1218 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1221 tbm_queue_sequence *data = surface_queue->impl_data;
1222 queue_node *next = NULL;
1223 queue_node *tmp = NULL;
1225 node->priv_flags = 0;
1227 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1228 if (next->priv_flags)
1230 _queue_node_pop(&data->dequeue_list, next);
1231 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1236 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1239 tbm_queue_sequence *data = surface_queue->impl_data;
1240 queue_node *node = NULL;
1242 node = _tbm_surface_queue_dequeue(surface_queue);
1244 _queue_node_push_back(&data->dequeue_list, node);
1245 node->priv_flags = 1;
1251 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1252 __tbm_queue_sequence_init,
1253 __tbm_queue_sequence_reset,
1254 __tbm_queue_sequence_destroy,
1255 __tbm_queue_sequence_need_attach,
1256 __tbm_queue_sequence_enqueue,
1257 NULL, /*__tbm_queue_sequence_release*/
1258 __tbm_queue_sequence_dequeue,
1259 NULL, /*__tbm_queue_sequence_acquire*/
1263 tbm_surface_queue_sequence_create(int queue_size, int width,
1264 int height, int format, int flags)
1266 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1267 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1268 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1269 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1271 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1272 sizeof(struct _tbm_surface_queue));
1273 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1277 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1278 sizeof(tbm_queue_sequence));
1280 free(surface_queue);
1284 data->queue_size = queue_size;
1285 data->flags = flags;
1286 _tbm_surface_queue_init(surface_queue,
1288 width, height, format,
1289 &tbm_queue_sequence_impl, data);
1291 return surface_queue;