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 typedef enum _queue_node_type {
57 QUEUE_NODE_TYPE_DEQUEUE,
58 QUEUE_NODE_TYPE_ENQUEUE,
59 QUEUE_NODE_TYPE_ACQUIRE,
60 QUEUE_NODE_TYPE_RELEASE
64 struct list_head head;
69 tbm_surface_h surface;
71 struct list_head item_link;
72 struct list_head link;
76 unsigned int priv_flags; /*for each queue*/
80 struct list_head link;
82 tbm_surface_queue_notify_cb cb;
86 typedef struct _tbm_surface_queue_interface {
87 void (*init)(tbm_surface_queue_h queue);
88 void (*reset)(tbm_surface_queue_h queue);
89 void (*destroy)(tbm_surface_queue_h queue);
90 void (*need_attach)(tbm_surface_queue_h queue);
92 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
93 void (*release)(tbm_surface_queue_h queue, queue_node *node);
94 queue_node *(*dequeue)(tbm_surface_queue_h queue);
95 queue_node *(*acquire)(tbm_surface_queue_h queue);
96 } tbm_surface_queue_interface;
98 struct _tbm_surface_queue {
106 struct list_head list;
108 struct list_head destory_noti;
109 struct list_head dequeuable_noti;
110 struct list_head dequeue_noti;
111 struct list_head acquirable_noti;
112 struct list_head reset_noti;
114 pthread_mutex_t lock;
115 pthread_cond_t free_cond;
116 pthread_cond_t dirty_cond;
118 const tbm_surface_queue_interface *impl;
121 //For external buffer allocation
122 tbm_surface_alloc_cb alloc_cb;
123 tbm_surface_free_cb free_cb;
127 /* LCOV_EXCL_START */
129 _queue_node_create(void)
131 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
133 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
139 _queue_node_delete(queue_node *node)
141 LIST_DEL(&node->item_link);
142 LIST_DEL(&node->link);
147 _queue_is_empty(queue *queue)
149 if (LIST_IS_EMPTY(&queue->head))
156 _queue_node_push_back(queue *queue, queue_node *node)
158 LIST_ADDTAIL(&node->item_link, &queue->head);
163 _queue_node_push_front(queue *queue, queue_node *node)
165 LIST_ADD(&node->item_link, &queue->head);
170 _queue_node_pop_front(queue *queue)
172 queue_node *node = NULL;
174 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
176 LIST_DEL(&node->item_link);
183 _queue_node_pop(queue *queue, queue_node *node)
185 LIST_DEL(&node->item_link);
192 _queue_has_node_type(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
194 queue_node *node = NULL;
195 queue_node *tmp = NULL;
197 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
198 if (node->type == type)
206 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
207 tbm_surface_h surface, int *out_type)
209 queue_node *node = NULL;
210 queue_node *tmp = NULL;
213 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
217 if (type & FREE_QUEUE) {
218 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
220 if (node->surface == surface) {
222 *out_type = FREE_QUEUE;
229 if (type & DIRTY_QUEUE) {
230 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
232 if (node->surface == surface) {
234 *out_type = DIRTY_QUEUE;
241 if (type & NODE_LIST) {
242 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
243 if (node->surface == surface) {
245 *out_type = NODE_LIST;
256 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
259 if (surface_queue->free_cb) {
260 surface_queue->free_cb(surface_queue,
261 surface_queue->alloc_cb_data,
265 tbm_surface_destroy(node->surface);
268 _queue_node_delete(node);
272 _queue_init(queue *queue)
274 LIST_INITHEAD(&queue->head);
280 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
283 TBM_RETURN_IF_FAIL(cb != NULL);
285 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
287 TBM_RETURN_IF_FAIL(item != NULL);
289 LIST_INITHEAD(&item->link);
293 LIST_ADDTAIL(&item->link, list);
297 _notify_remove(struct list_head *list,
298 tbm_surface_queue_notify_cb cb, void *data)
300 queue_notify *item = NULL, *tmp = NULL;
302 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
303 if (item->cb == cb && item->data == data) {
304 LIST_DEL(&item->link);
310 TBM_LOG_E("Cannot find notifiy\n");
314 _notify_remove_all(struct list_head *list)
316 queue_notify *item = NULL, *tmp = NULL;
318 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
319 LIST_DEL(&item->link);
325 _notify_emit(tbm_surface_queue_h surface_queue,
326 struct list_head *list)
328 queue_notify *item = NULL, *tmp = NULL;
330 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
331 item->cb(surface_queue, item->data);
336 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
338 queue_node *node = NULL;
339 queue_node *tmp = NULL;
342 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
343 if (node->type == type)
351 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
352 tbm_surface_h surface)
354 queue_node *node = NULL;
356 node = _queue_node_create();
357 TBM_RETURN_IF_FAIL(node != NULL);
359 tbm_surface_internal_ref(surface);
360 node->surface = surface;
362 LIST_ADDTAIL(&node->link, &surface_queue->list);
363 _queue_node_push_back(&surface_queue->free_queue, node);
367 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
368 tbm_surface_h surface)
370 queue_node *node = NULL;
373 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
375 _queue_delete_node(surface_queue, node);
379 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
380 queue_node *node, int push_back)
383 _queue_node_push_back(&surface_queue->dirty_queue, node);
385 _queue_node_push_front(&surface_queue->dirty_queue, node);
389 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
391 queue_node *node = NULL;
393 if (_queue_is_empty(&surface_queue->free_queue)) {
394 if (surface_queue->impl && surface_queue->impl->need_attach)
395 surface_queue->impl->need_attach(surface_queue);
397 if (_queue_is_empty(&surface_queue->free_queue))
401 node = _queue_node_pop_front(&surface_queue->free_queue);
407 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
409 queue_node *node = NULL;
411 if (_queue_is_empty(&surface_queue->dirty_queue))
414 node = _queue_node_pop_front(&surface_queue->dirty_queue);
420 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
421 queue_node *node, int push_back)
424 _queue_node_push_back(&surface_queue->free_queue, node);
426 _queue_node_push_front(&surface_queue->free_queue, node);
430 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
432 int width, int height, int format,
433 const tbm_surface_queue_interface *impl, void *data)
435 TBM_RETURN_IF_FAIL(surface_queue != NULL);
436 TBM_RETURN_IF_FAIL(impl != NULL);
438 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
440 pthread_mutex_init(&surface_queue->lock, NULL);
441 pthread_cond_init(&surface_queue->free_cond, NULL);
442 pthread_cond_init(&surface_queue->dirty_cond, NULL);
444 surface_queue->queue_size = queue_size;
445 surface_queue->width = width;
446 surface_queue->height = height;
447 surface_queue->format = format;
448 surface_queue->impl = impl;
449 surface_queue->impl_data = data;
451 _queue_init(&surface_queue->free_queue);
452 _queue_init(&surface_queue->dirty_queue);
453 LIST_INITHEAD(&surface_queue->list);
455 LIST_INITHEAD(&surface_queue->destory_noti);
456 LIST_INITHEAD(&surface_queue->acquirable_noti);
457 LIST_INITHEAD(&surface_queue->dequeuable_noti);
458 LIST_INITHEAD(&surface_queue->dequeue_noti);
459 LIST_INITHEAD(&surface_queue->reset_noti);
461 if (surface_queue->impl && surface_queue->impl->init)
462 surface_queue->impl->init(surface_queue);
465 tbm_surface_queue_error_e
466 tbm_surface_queue_add_destroy_cb(
467 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
470 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
471 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
473 pthread_mutex_lock(&surface_queue->lock);
475 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
477 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
479 pthread_mutex_unlock(&surface_queue->lock);
481 return TBM_SURFACE_QUEUE_ERROR_NONE;
484 tbm_surface_queue_error_e
485 tbm_surface_queue_remove_destroy_cb(
486 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
489 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
490 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
492 pthread_mutex_lock(&surface_queue->lock);
494 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
496 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
498 pthread_mutex_unlock(&surface_queue->lock);
500 return TBM_SURFACE_QUEUE_ERROR_NONE;
503 tbm_surface_queue_error_e
504 tbm_surface_queue_add_dequeuable_cb(
505 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
508 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
509 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
511 pthread_mutex_lock(&surface_queue->lock);
513 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
515 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
517 pthread_mutex_unlock(&surface_queue->lock);
519 return TBM_SURFACE_QUEUE_ERROR_NONE;
522 tbm_surface_queue_error_e
523 tbm_surface_queue_remove_dequeuable_cb(
524 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
527 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
528 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
530 pthread_mutex_lock(&surface_queue->lock);
532 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
534 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
536 pthread_mutex_unlock(&surface_queue->lock);
538 return TBM_SURFACE_QUEUE_ERROR_NONE;
541 tbm_surface_queue_error_e
542 tbm_surface_queue_add_dequeue_cb(
543 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
546 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
547 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
549 pthread_mutex_lock(&surface_queue->lock);
551 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
553 _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
555 pthread_mutex_unlock(&surface_queue->lock);
557 return TBM_SURFACE_QUEUE_ERROR_NONE;
560 tbm_surface_queue_error_e
561 tbm_surface_queue_remove_dequeue_cb(
562 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
565 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
566 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
568 pthread_mutex_lock(&surface_queue->lock);
570 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
572 _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
574 pthread_mutex_unlock(&surface_queue->lock);
576 return TBM_SURFACE_QUEUE_ERROR_NONE;
579 tbm_surface_queue_error_e
580 tbm_surface_queue_add_acquirable_cb(
581 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
584 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
585 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
587 pthread_mutex_lock(&surface_queue->lock);
589 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
591 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
593 pthread_mutex_unlock(&surface_queue->lock);
595 return TBM_SURFACE_QUEUE_ERROR_NONE;
598 tbm_surface_queue_error_e
599 tbm_surface_queue_remove_acquirable_cb(
600 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
603 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
604 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
606 pthread_mutex_lock(&surface_queue->lock);
608 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
610 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
612 pthread_mutex_unlock(&surface_queue->lock);
614 return TBM_SURFACE_QUEUE_ERROR_NONE;
617 tbm_surface_queue_error_e
618 tbm_surface_queue_set_alloc_cb(
619 tbm_surface_queue_h surface_queue,
620 tbm_surface_alloc_cb alloc_cb,
621 tbm_surface_free_cb free_cb,
624 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
625 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
627 pthread_mutex_lock(&surface_queue->lock);
629 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
631 surface_queue->alloc_cb = alloc_cb;
632 surface_queue->free_cb = free_cb;
633 surface_queue->alloc_cb_data = data;
635 pthread_mutex_unlock(&surface_queue->lock);
637 return TBM_SURFACE_QUEUE_ERROR_NONE;
641 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
643 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
645 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
647 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
649 return surface_queue->width;
653 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
655 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
657 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
659 return surface_queue->height;
663 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
665 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
667 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
669 return surface_queue->format;
673 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
675 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
677 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
679 return surface_queue->queue_size;
682 tbm_surface_queue_error_e
683 tbm_surface_queue_add_reset_cb(
684 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
687 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
688 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
690 pthread_mutex_lock(&surface_queue->lock);
692 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
694 _notify_add(&surface_queue->reset_noti, reset_cb, data);
696 pthread_mutex_unlock(&surface_queue->lock);
698 return TBM_SURFACE_QUEUE_ERROR_NONE;
701 tbm_surface_queue_error_e
702 tbm_surface_queue_remove_reset_cb(
703 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
706 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
707 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
709 pthread_mutex_lock(&surface_queue->lock);
711 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
713 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
715 pthread_mutex_unlock(&surface_queue->lock);
717 return TBM_SURFACE_QUEUE_ERROR_NONE;
720 tbm_surface_queue_error_e
721 tbm_surface_queue_enqueue(tbm_surface_queue_h
722 surface_queue, tbm_surface_h surface)
724 queue_node *node = NULL;
727 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
728 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
729 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
730 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
733 tbm_surface_internal_dump_buffer(surface, "enqueue");
735 pthread_mutex_lock(&surface_queue->lock);
737 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
739 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
740 if (node == NULL || queue_type != NODE_LIST) {
741 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
743 pthread_mutex_unlock(&surface_queue->lock);
744 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
747 if (surface_queue->impl && surface_queue->impl->enqueue)
748 surface_queue->impl->enqueue(surface_queue, node);
750 _tbm_surface_queue_enqueue(surface_queue, node, 1);
752 if (_queue_is_empty(&surface_queue->dirty_queue)) {
753 pthread_mutex_unlock(&surface_queue->lock);
754 return TBM_SURFACE_QUEUE_ERROR_NONE;
757 node->type = QUEUE_NODE_TYPE_ENQUEUE;
759 pthread_mutex_unlock(&surface_queue->lock);
760 pthread_cond_signal(&surface_queue->dirty_cond);
762 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
764 return TBM_SURFACE_QUEUE_ERROR_NONE;
767 tbm_surface_queue_error_e
768 tbm_surface_queue_dequeue(tbm_surface_queue_h
769 surface_queue, tbm_surface_h *surface)
771 queue_node *node = NULL;
773 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
774 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
775 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
776 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
778 pthread_mutex_lock(&surface_queue->lock);
780 if (surface_queue->impl && surface_queue->impl->dequeue)
781 node = surface_queue->impl->dequeue(surface_queue);
783 node = _tbm_surface_queue_dequeue(surface_queue);
787 pthread_mutex_unlock(&surface_queue->lock);
788 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
791 if (node->surface == NULL) {
793 TBM_LOG_E("_queue_node_pop_front failed\n");
794 pthread_mutex_unlock(&surface_queue->lock);
795 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
798 node->type = QUEUE_NODE_TYPE_DEQUEUE;
799 *surface = node->surface;
801 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
803 pthread_mutex_unlock(&surface_queue->lock);
805 _notify_emit(surface_queue, &surface_queue->dequeue_noti);
807 return TBM_SURFACE_QUEUE_ERROR_NONE;
811 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
813 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
815 pthread_mutex_lock(&surface_queue->lock);
817 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
819 if (_queue_is_empty(&surface_queue->free_queue)) {
820 if (surface_queue->impl && surface_queue->impl->need_attach)
821 surface_queue->impl->need_attach(surface_queue);
824 if (_queue_is_empty(&surface_queue->free_queue)) {
826 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) {
828 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
829 pthread_mutex_unlock(&surface_queue->lock);
833 pthread_mutex_unlock(&surface_queue->lock);
837 pthread_mutex_unlock(&surface_queue->lock);
842 tbm_surface_queue_error_e
843 tbm_surface_queue_release(tbm_surface_queue_h
844 surface_queue, tbm_surface_h surface)
846 queue_node *node = NULL;
849 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
850 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
851 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
852 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
854 pthread_mutex_lock(&surface_queue->lock);
856 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
858 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
859 if (node == NULL || queue_type != NODE_LIST) {
860 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
862 pthread_mutex_unlock(&surface_queue->lock);
863 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
866 if (surface_queue->impl && surface_queue->impl->release)
867 surface_queue->impl->release(surface_queue, node);
869 _tbm_surface_queue_release(surface_queue, node, 1);
871 if (_queue_is_empty(&surface_queue->free_queue)) {
872 pthread_mutex_unlock(&surface_queue->lock);
873 return TBM_SURFACE_QUEUE_ERROR_NONE;
876 node->type = QUEUE_NODE_TYPE_RELEASE;
878 pthread_mutex_unlock(&surface_queue->lock);
879 pthread_cond_signal(&surface_queue->free_cond);
881 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
883 return TBM_SURFACE_QUEUE_ERROR_NONE;
886 tbm_surface_queue_error_e
887 tbm_surface_queue_acquire(tbm_surface_queue_h
888 surface_queue, tbm_surface_h *surface)
890 queue_node *node = NULL;
892 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
893 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
894 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
895 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
897 pthread_mutex_lock(&surface_queue->lock);
899 if (surface_queue->impl && surface_queue->impl->acquire)
900 node = surface_queue->impl->acquire(surface_queue);
902 node = _tbm_surface_queue_acquire(surface_queue);
906 pthread_mutex_unlock(&surface_queue->lock);
907 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
910 if (node->surface == NULL) {
912 TBM_LOG_E("_queue_node_pop_front failed\n");
913 pthread_mutex_unlock(&surface_queue->lock);
914 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
917 node->type = QUEUE_NODE_TYPE_ACQUIRE;
919 *surface = node->surface;
921 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
923 pthread_mutex_unlock(&surface_queue->lock);
926 tbm_surface_internal_dump_buffer(*surface, "acquire");
928 return TBM_SURFACE_QUEUE_ERROR_NONE;
932 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
934 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
936 pthread_mutex_lock(&surface_queue->lock);
938 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
940 if (_queue_is_empty(&surface_queue->dirty_queue)) {
942 _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
944 if (!_queue_has_node_type(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
945 TBM_LOG_E("Deosn't have dequeue type node\n");
946 pthread_mutex_unlock(&surface_queue->lock);
950 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
951 pthread_mutex_unlock(&surface_queue->lock);
955 pthread_mutex_unlock(&surface_queue->lock);
959 pthread_mutex_unlock(&surface_queue->lock);
965 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
967 queue_node *node = NULL, *tmp = NULL;
969 TBM_RETURN_IF_FAIL(surface_queue != NULL);
971 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
973 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
974 _queue_delete_node(surface_queue, node);
977 _notify_emit(surface_queue, &surface_queue->destory_noti);
979 if (surface_queue->impl && surface_queue->impl->destroy)
980 surface_queue->impl->destroy(surface_queue);
982 _notify_remove_all(&surface_queue->destory_noti);
983 _notify_remove_all(&surface_queue->acquirable_noti);
984 _notify_remove_all(&surface_queue->dequeuable_noti);
985 _notify_remove_all(&surface_queue->reset_noti);
987 pthread_mutex_destroy(&surface_queue->lock);
991 tbm_surface_queue_error_e
992 tbm_surface_queue_reset(tbm_surface_queue_h
993 surface_queue, int width, int height, int format)
995 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
996 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
998 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1000 queue_node *node = NULL, *tmp = NULL;
1002 if (width == surface_queue->width && height == surface_queue->height &&
1003 format == surface_queue->format)
1004 return TBM_SURFACE_QUEUE_ERROR_NONE;
1006 pthread_mutex_lock(&surface_queue->lock);
1008 surface_queue->width = width;
1009 surface_queue->height = height;
1010 surface_queue->format = format;
1012 /* Destory surface and Push to free_queue */
1013 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1014 _queue_delete_node(surface_queue, node);
1018 _queue_init(&surface_queue->free_queue);
1019 _queue_init(&surface_queue->dirty_queue);
1020 LIST_INITHEAD(&surface_queue->list);
1022 if (surface_queue->impl && surface_queue->impl->reset)
1023 surface_queue->impl->reset(surface_queue);
1025 pthread_mutex_unlock(&surface_queue->lock);
1026 pthread_cond_signal(&surface_queue->free_cond);
1028 _notify_emit(surface_queue, &surface_queue->reset_noti);
1030 return TBM_SURFACE_QUEUE_ERROR_NONE;
1033 tbm_surface_queue_error_e
1034 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1036 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1037 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1039 queue_node *node = NULL, *tmp = NULL;
1041 pthread_mutex_lock(&surface_queue->lock);
1043 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1045 /* Destory surface and Push to free_queue */
1046 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1047 _queue_delete_node(surface_queue, node);
1051 _queue_init(&surface_queue->free_queue);
1052 _queue_init(&surface_queue->dirty_queue);
1053 LIST_INITHEAD(&surface_queue->list);
1055 if (surface_queue->impl && surface_queue->impl->reset)
1056 surface_queue->impl->reset(surface_queue);
1058 pthread_mutex_unlock(&surface_queue->lock);
1059 pthread_cond_signal(&surface_queue->free_cond);
1061 _notify_emit(surface_queue, &surface_queue->reset_noti);
1063 return TBM_SURFACE_QUEUE_ERROR_NONE;
1066 tbm_surface_queue_error_e
1067 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1068 tbm_surface_h *surfaces, int *num)
1070 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1071 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1072 TBM_RETURN_VAL_IF_FAIL(num != NULL,
1073 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1075 queue_node *node = NULL;
1076 queue_node *tmp = NULL;
1078 pthread_mutex_lock(&surface_queue->lock);
1081 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1083 surfaces[*num] = node->surface;
1088 pthread_mutex_unlock(&surface_queue->lock);
1090 return TBM_SURFACE_QUEUE_ERROR_NONE;
1097 } tbm_queue_default;
1100 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1102 tbm_queue_default *data = surface_queue->impl_data;
1104 data->num_attached = 0;
1108 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1110 tbm_queue_default *data = surface_queue->impl_data;
1112 data->num_attached = 0;
1116 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1118 free(surface_queue->impl_data);
1122 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1124 tbm_queue_default *data = surface_queue->impl_data;
1125 tbm_surface_h surface;
1127 if (data->queue_size == data->num_attached)
1130 if (surface_queue->alloc_cb) {
1131 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1132 TBM_RETURN_IF_FAIL(surface != NULL);
1133 tbm_surface_internal_ref(surface);
1135 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1136 surface_queue->height,
1137 surface_queue->format,
1139 TBM_RETURN_IF_FAIL(surface != NULL);
1142 _tbm_surface_queue_attach(surface_queue, surface);
1143 tbm_surface_internal_unref(surface);
1144 data->num_attached++;
1147 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1148 __tbm_queue_default_init,
1149 __tbm_queue_default_reset,
1150 __tbm_queue_default_destroy,
1151 __tbm_queue_default_need_attach,
1152 NULL, /*__tbm_queue_default_enqueue*/
1153 NULL, /*__tbm_queue_default_release*/
1154 NULL, /*__tbm_queue_default_dequeue*/
1155 NULL, /*__tbm_queue_default_acquire*/
1159 tbm_surface_queue_create(int queue_size, int width,
1160 int height, int format, int flags)
1162 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1163 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1164 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1165 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1167 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1168 sizeof(struct _tbm_surface_queue));
1169 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1171 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1173 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1174 sizeof(tbm_queue_default));
1176 free(surface_queue);
1180 data->queue_size = queue_size;
1181 data->flags = flags;
1182 _tbm_surface_queue_init(surface_queue,
1184 width, height, format,
1185 &tbm_queue_default_impl, data);
1187 return surface_queue;
1195 } tbm_queue_sequence;
1198 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1200 tbm_queue_sequence *data = surface_queue->impl_data;
1202 data->num_attached = 0;
1203 _queue_init(&data->dequeue_list);
1207 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1209 tbm_queue_sequence *data = surface_queue->impl_data;
1211 data->num_attached = 0;
1212 _queue_init(&data->dequeue_list);
1216 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1218 free(surface_queue->impl_data);
1222 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1224 tbm_queue_sequence *data = surface_queue->impl_data;
1225 tbm_surface_h surface;
1227 if (data->queue_size == data->num_attached)
1230 if (surface_queue->alloc_cb) {
1231 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1232 TBM_RETURN_IF_FAIL(surface != NULL);
1233 tbm_surface_internal_ref(surface);
1235 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1236 surface_queue->height,
1237 surface_queue->format,
1239 TBM_RETURN_IF_FAIL(surface != NULL);
1242 _tbm_surface_queue_attach(surface_queue, surface);
1243 tbm_surface_internal_unref(surface);
1244 data->num_attached++;
1248 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1251 tbm_queue_sequence *data = surface_queue->impl_data;
1252 queue_node *next = NULL;
1253 queue_node *tmp = NULL;
1255 node->priv_flags = 0;
1257 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1258 if (next->priv_flags)
1260 _queue_node_pop(&data->dequeue_list, next);
1261 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1266 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1269 tbm_queue_sequence *data = surface_queue->impl_data;
1270 queue_node *node = NULL;
1272 node = _tbm_surface_queue_dequeue(surface_queue);
1274 _queue_node_push_back(&data->dequeue_list, node);
1275 node->priv_flags = 1;
1281 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1282 __tbm_queue_sequence_init,
1283 __tbm_queue_sequence_reset,
1284 __tbm_queue_sequence_destroy,
1285 __tbm_queue_sequence_need_attach,
1286 __tbm_queue_sequence_enqueue,
1287 NULL, /*__tbm_queue_sequence_release*/
1288 __tbm_queue_sequence_dequeue,
1289 NULL, /*__tbm_queue_sequence_acquire*/
1293 tbm_surface_queue_sequence_create(int queue_size, int width,
1294 int height, int format, int flags)
1296 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1297 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1298 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1299 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1301 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1302 sizeof(struct _tbm_surface_queue));
1303 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1305 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1307 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1308 sizeof(tbm_queue_sequence));
1310 free(surface_queue);
1314 data->queue_size = queue_size;
1315 data->flags = flags;
1316 _tbm_surface_queue_init(surface_queue,
1318 width, height, format,
1319 &tbm_queue_sequence_impl, data);
1321 return surface_queue;
1323 /* LCOV_EXCL_STOP */