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 acquirable_noti;
111 struct list_head reset_noti;
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;
126 /* LCOV_EXCL_START */
128 _queue_node_create(void)
130 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
132 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
138 _queue_node_delete(queue_node *node)
140 LIST_DEL(&node->item_link);
141 LIST_DEL(&node->link);
146 _queue_is_empty(queue *queue)
148 if (LIST_IS_EMPTY(&queue->head))
155 _queue_node_push_back(queue *queue, queue_node *node)
157 LIST_ADDTAIL(&node->item_link, &queue->head);
162 _queue_node_push_front(queue *queue, queue_node *node)
164 LIST_ADD(&node->item_link, &queue->head);
169 _queue_node_pop_front(queue *queue)
171 queue_node *node = NULL;
173 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
175 LIST_DEL(&node->item_link);
182 _queue_node_pop(queue *queue, queue_node *node)
184 LIST_DEL(&node->item_link);
191 _queue_has_node_type(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
193 queue_node *node = NULL;
194 queue_node *tmp = NULL;
196 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
197 if (node->type == type)
205 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
206 tbm_surface_h surface, int *out_type)
208 queue_node *node = NULL;
209 queue_node *tmp = NULL;
212 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
216 if (type & FREE_QUEUE) {
217 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
219 if (node->surface == surface) {
221 *out_type = FREE_QUEUE;
228 if (type & DIRTY_QUEUE) {
229 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
231 if (node->surface == surface) {
233 *out_type = DIRTY_QUEUE;
240 if (type & NODE_LIST) {
241 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
242 if (node->surface == surface) {
244 *out_type = NODE_LIST;
255 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
258 if (surface_queue->free_cb) {
259 surface_queue->free_cb(surface_queue,
260 surface_queue->alloc_cb_data,
264 tbm_surface_destroy(node->surface);
267 _queue_node_delete(node);
271 _queue_init(queue *queue)
273 LIST_INITHEAD(&queue->head);
279 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
282 TBM_RETURN_IF_FAIL(cb != NULL);
284 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
286 TBM_RETURN_IF_FAIL(item != NULL);
288 LIST_INITHEAD(&item->link);
292 LIST_ADDTAIL(&item->link, list);
296 _notify_remove(struct list_head *list,
297 tbm_surface_queue_notify_cb cb, void *data)
299 queue_notify *item = NULL, *tmp = NULL;
301 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
302 if (item->cb == cb && item->data == data) {
303 LIST_DEL(&item->link);
309 TBM_LOG_E("Cannot find notifiy\n");
313 _notify_remove_all(struct list_head *list)
315 queue_notify *item = NULL, *tmp = NULL;
317 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
318 LIST_DEL(&item->link);
324 _notify_emit(tbm_surface_queue_h surface_queue,
325 struct list_head *list)
327 queue_notify *item = NULL, *tmp = NULL;
329 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
330 item->cb(surface_queue, item->data);
335 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
337 queue_node *node = NULL;
338 queue_node *tmp = NULL;
341 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
342 if (node->type == type)
350 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
351 tbm_surface_h surface)
353 queue_node *node = NULL;
355 node = _queue_node_create();
356 TBM_RETURN_IF_FAIL(node != NULL);
358 tbm_surface_internal_ref(surface);
359 node->surface = surface;
361 LIST_ADDTAIL(&node->link, &surface_queue->list);
362 _queue_node_push_back(&surface_queue->free_queue, node);
366 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
367 tbm_surface_h surface)
369 queue_node *node = NULL;
372 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
374 _queue_delete_node(surface_queue, node);
378 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
379 queue_node *node, int push_back)
382 _queue_node_push_back(&surface_queue->dirty_queue, node);
384 _queue_node_push_front(&surface_queue->dirty_queue, node);
388 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
390 queue_node *node = NULL;
392 if (_queue_is_empty(&surface_queue->free_queue)) {
393 if (surface_queue->impl && surface_queue->impl->need_attach)
394 surface_queue->impl->need_attach(surface_queue);
396 if (_queue_is_empty(&surface_queue->free_queue))
400 node = _queue_node_pop_front(&surface_queue->free_queue);
406 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
408 queue_node *node = NULL;
410 if (_queue_is_empty(&surface_queue->dirty_queue))
413 node = _queue_node_pop_front(&surface_queue->dirty_queue);
419 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
420 queue_node *node, int push_back)
423 _queue_node_push_back(&surface_queue->free_queue, node);
425 _queue_node_push_front(&surface_queue->free_queue, node);
429 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
431 int width, int height, int format,
432 const tbm_surface_queue_interface *impl, void *data)
434 TBM_RETURN_IF_FAIL(surface_queue != NULL);
435 TBM_RETURN_IF_FAIL(impl != NULL);
437 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
439 pthread_mutex_init(&surface_queue->lock, NULL);
440 pthread_cond_init(&surface_queue->free_cond, NULL);
441 pthread_cond_init(&surface_queue->dirty_cond, NULL);
443 surface_queue->queue_size = queue_size;
444 surface_queue->width = width;
445 surface_queue->height = height;
446 surface_queue->format = format;
447 surface_queue->impl = impl;
448 surface_queue->impl_data = data;
450 _queue_init(&surface_queue->free_queue);
451 _queue_init(&surface_queue->dirty_queue);
452 LIST_INITHEAD(&surface_queue->list);
454 LIST_INITHEAD(&surface_queue->destory_noti);
455 LIST_INITHEAD(&surface_queue->acquirable_noti);
456 LIST_INITHEAD(&surface_queue->dequeuable_noti);
457 LIST_INITHEAD(&surface_queue->reset_noti);
459 if (surface_queue->impl && surface_queue->impl->init)
460 surface_queue->impl->init(surface_queue);
463 tbm_surface_queue_error_e
464 tbm_surface_queue_add_destroy_cb(
465 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
468 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
469 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
471 pthread_mutex_lock(&surface_queue->lock);
473 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
475 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
477 pthread_mutex_unlock(&surface_queue->lock);
479 return TBM_SURFACE_QUEUE_ERROR_NONE;
482 tbm_surface_queue_error_e
483 tbm_surface_queue_remove_destroy_cb(
484 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
487 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
488 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
490 pthread_mutex_lock(&surface_queue->lock);
492 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
494 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
496 pthread_mutex_unlock(&surface_queue->lock);
498 return TBM_SURFACE_QUEUE_ERROR_NONE;
501 tbm_surface_queue_error_e
502 tbm_surface_queue_add_dequeuable_cb(
503 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
506 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
507 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
509 pthread_mutex_lock(&surface_queue->lock);
511 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
513 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
515 pthread_mutex_unlock(&surface_queue->lock);
517 return TBM_SURFACE_QUEUE_ERROR_NONE;
520 tbm_surface_queue_error_e
521 tbm_surface_queue_remove_dequeuable_cb(
522 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
525 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
526 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
528 pthread_mutex_lock(&surface_queue->lock);
530 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
532 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
534 pthread_mutex_unlock(&surface_queue->lock);
536 return TBM_SURFACE_QUEUE_ERROR_NONE;
539 tbm_surface_queue_error_e
540 tbm_surface_queue_add_acquirable_cb(
541 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
544 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
545 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
547 pthread_mutex_lock(&surface_queue->lock);
549 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
551 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
553 pthread_mutex_unlock(&surface_queue->lock);
555 return TBM_SURFACE_QUEUE_ERROR_NONE;
558 tbm_surface_queue_error_e
559 tbm_surface_queue_remove_acquirable_cb(
560 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
563 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
564 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
566 pthread_mutex_lock(&surface_queue->lock);
568 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
570 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
572 pthread_mutex_unlock(&surface_queue->lock);
574 return TBM_SURFACE_QUEUE_ERROR_NONE;
577 tbm_surface_queue_error_e
578 tbm_surface_queue_set_alloc_cb(
579 tbm_surface_queue_h surface_queue,
580 tbm_surface_alloc_cb alloc_cb,
581 tbm_surface_free_cb free_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 surface_queue->alloc_cb = alloc_cb;
592 surface_queue->free_cb = free_cb;
593 surface_queue->alloc_cb_data = data;
595 pthread_mutex_unlock(&surface_queue->lock);
597 return TBM_SURFACE_QUEUE_ERROR_NONE;
601 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
603 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
605 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
607 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
609 return surface_queue->width;
613 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
615 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
617 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
619 return surface_queue->height;
623 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
625 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
627 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
629 return surface_queue->format;
633 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
635 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
637 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
639 return surface_queue->queue_size;
642 tbm_surface_queue_error_e
643 tbm_surface_queue_add_reset_cb(
644 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
647 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
648 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
650 pthread_mutex_lock(&surface_queue->lock);
652 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
654 _notify_add(&surface_queue->reset_noti, reset_cb, data);
656 pthread_mutex_unlock(&surface_queue->lock);
658 return TBM_SURFACE_QUEUE_ERROR_NONE;
661 tbm_surface_queue_error_e
662 tbm_surface_queue_remove_reset_cb(
663 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
666 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
667 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
669 pthread_mutex_lock(&surface_queue->lock);
671 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
673 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
675 pthread_mutex_unlock(&surface_queue->lock);
677 return TBM_SURFACE_QUEUE_ERROR_NONE;
680 tbm_surface_queue_error_e
681 tbm_surface_queue_enqueue(tbm_surface_queue_h
682 surface_queue, tbm_surface_h surface)
684 queue_node *node = NULL;
687 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
688 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
689 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
690 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
693 tbm_surface_internal_dump_buffer(surface, "enqueue");
695 pthread_mutex_lock(&surface_queue->lock);
697 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
699 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
700 if (node == NULL || queue_type != NODE_LIST) {
701 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
703 pthread_mutex_unlock(&surface_queue->lock);
704 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
707 if (surface_queue->impl && surface_queue->impl->enqueue)
708 surface_queue->impl->enqueue(surface_queue, node);
710 _tbm_surface_queue_enqueue(surface_queue, node, 1);
712 if (_queue_is_empty(&surface_queue->dirty_queue)) {
713 pthread_mutex_unlock(&surface_queue->lock);
714 return TBM_SURFACE_QUEUE_ERROR_NONE;
717 node->type = QUEUE_NODE_TYPE_ENQUEUE;
719 pthread_mutex_unlock(&surface_queue->lock);
720 pthread_cond_signal(&surface_queue->dirty_cond);
722 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
724 return TBM_SURFACE_QUEUE_ERROR_NONE;
727 tbm_surface_queue_error_e
728 tbm_surface_queue_dequeue(tbm_surface_queue_h
729 surface_queue, tbm_surface_h *surface)
731 queue_node *node = NULL;
733 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
734 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
735 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
736 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
738 pthread_mutex_lock(&surface_queue->lock);
740 if (surface_queue->impl && surface_queue->impl->dequeue)
741 node = surface_queue->impl->dequeue(surface_queue);
743 node = _tbm_surface_queue_dequeue(surface_queue);
747 pthread_mutex_unlock(&surface_queue->lock);
748 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
751 if (node->surface == NULL) {
753 TBM_LOG_E("_queue_node_pop_front failed\n");
754 pthread_mutex_unlock(&surface_queue->lock);
755 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
758 node->type = QUEUE_NODE_TYPE_DEQUEUE;
759 *surface = node->surface;
761 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
763 pthread_mutex_unlock(&surface_queue->lock);
765 return TBM_SURFACE_QUEUE_ERROR_NONE;
769 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
771 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
773 pthread_mutex_lock(&surface_queue->lock);
775 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
777 if (_queue_is_empty(&surface_queue->free_queue)) {
778 if (surface_queue->impl && surface_queue->impl->need_attach)
779 surface_queue->impl->need_attach(surface_queue);
782 if (_queue_is_empty(&surface_queue->free_queue)) {
784 _tbm_surface_queue_get_node_count(surface_queue,QUEUE_NODE_TYPE_ACQUIRE)) {
786 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
787 pthread_mutex_unlock(&surface_queue->lock);
791 pthread_mutex_unlock(&surface_queue->lock);
795 pthread_mutex_unlock(&surface_queue->lock);
800 tbm_surface_queue_error_e
801 tbm_surface_queue_release(tbm_surface_queue_h
802 surface_queue, tbm_surface_h surface)
804 queue_node *node = NULL;
807 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
808 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
809 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
810 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
812 pthread_mutex_lock(&surface_queue->lock);
814 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
816 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
817 if (node == NULL || queue_type != NODE_LIST) {
818 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
820 pthread_mutex_unlock(&surface_queue->lock);
821 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
824 if (surface_queue->impl && surface_queue->impl->release)
825 surface_queue->impl->release(surface_queue, node);
827 _tbm_surface_queue_release(surface_queue, node, 1);
829 if (_queue_is_empty(&surface_queue->free_queue)) {
830 pthread_mutex_unlock(&surface_queue->lock);
831 return TBM_SURFACE_QUEUE_ERROR_NONE;
834 node->type = QUEUE_NODE_TYPE_RELEASE;
836 pthread_mutex_unlock(&surface_queue->lock);
837 pthread_cond_signal(&surface_queue->free_cond);
839 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
841 return TBM_SURFACE_QUEUE_ERROR_NONE;
844 tbm_surface_queue_error_e
845 tbm_surface_queue_acquire(tbm_surface_queue_h
846 surface_queue, tbm_surface_h *surface)
848 queue_node *node = NULL;
850 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
851 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
852 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
853 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
855 pthread_mutex_lock(&surface_queue->lock);
857 if (surface_queue->impl && surface_queue->impl->acquire)
858 node = surface_queue->impl->acquire(surface_queue);
860 node = _tbm_surface_queue_acquire(surface_queue);
864 pthread_mutex_unlock(&surface_queue->lock);
865 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
868 if (node->surface == NULL) {
870 TBM_LOG_E("_queue_node_pop_front failed\n");
871 pthread_mutex_unlock(&surface_queue->lock);
872 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
875 node->type = QUEUE_NODE_TYPE_ACQUIRE;
877 *surface = node->surface;
879 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
881 pthread_mutex_unlock(&surface_queue->lock);
884 tbm_surface_internal_dump_buffer(*surface, "acquire");
886 return TBM_SURFACE_QUEUE_ERROR_NONE;
890 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
892 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
894 pthread_mutex_lock(&surface_queue->lock);
896 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
898 if (_queue_is_empty(&surface_queue->dirty_queue)) {
900 _tbm_surface_queue_get_node_count(surface_queue,QUEUE_NODE_TYPE_DEQUEUE)) {
902 if (!_queue_has_node_type(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
903 TBM_LOG_E("Deosn't have dequeue type node\n");
904 pthread_mutex_unlock(&surface_queue->lock);
908 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
909 pthread_mutex_unlock(&surface_queue->lock);
913 pthread_mutex_unlock(&surface_queue->lock);
917 pthread_mutex_unlock(&surface_queue->lock);
923 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
925 queue_node *node = NULL, *tmp = NULL;
927 TBM_RETURN_IF_FAIL(surface_queue != NULL);
929 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
931 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
932 _queue_delete_node(surface_queue, node);
935 _notify_emit(surface_queue, &surface_queue->destory_noti);
937 if (surface_queue->impl && surface_queue->impl->destroy)
938 surface_queue->impl->destroy(surface_queue);
940 _notify_remove_all(&surface_queue->destory_noti);
941 _notify_remove_all(&surface_queue->acquirable_noti);
942 _notify_remove_all(&surface_queue->dequeuable_noti);
943 _notify_remove_all(&surface_queue->reset_noti);
945 pthread_mutex_destroy(&surface_queue->lock);
949 tbm_surface_queue_error_e
950 tbm_surface_queue_reset(tbm_surface_queue_h
951 surface_queue, int width, int height, int format)
953 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
954 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
956 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
958 queue_node *node = NULL, *tmp = NULL;
960 if (width == surface_queue->width && height == surface_queue->height &&
961 format == surface_queue->format)
962 return TBM_SURFACE_QUEUE_ERROR_NONE;
964 pthread_mutex_lock(&surface_queue->lock);
966 surface_queue->width = width;
967 surface_queue->height = height;
968 surface_queue->format = format;
970 /* Destory surface and Push to free_queue */
971 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
972 _queue_delete_node(surface_queue, node);
976 _queue_init(&surface_queue->free_queue);
977 _queue_init(&surface_queue->dirty_queue);
978 LIST_INITHEAD(&surface_queue->list);
980 if (surface_queue->impl && surface_queue->impl->reset)
981 surface_queue->impl->reset(surface_queue);
983 pthread_mutex_unlock(&surface_queue->lock);
984 pthread_cond_signal(&surface_queue->free_cond);
986 _notify_emit(surface_queue, &surface_queue->reset_noti);
988 return TBM_SURFACE_QUEUE_ERROR_NONE;
991 tbm_surface_queue_error_e
992 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
994 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
995 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
997 queue_node *node = NULL, *tmp = NULL;
999 pthread_mutex_lock(&surface_queue->lock);
1001 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1003 /* Destory surface and Push to free_queue */
1004 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1005 _queue_delete_node(surface_queue, node);
1009 _queue_init(&surface_queue->free_queue);
1010 _queue_init(&surface_queue->dirty_queue);
1011 LIST_INITHEAD(&surface_queue->list);
1013 if (surface_queue->impl && surface_queue->impl->reset)
1014 surface_queue->impl->reset(surface_queue);
1016 _notify_emit(surface_queue, &surface_queue->reset_noti);
1018 pthread_mutex_unlock(&surface_queue->lock);
1019 pthread_cond_signal(&surface_queue->free_cond);
1021 return TBM_SURFACE_QUEUE_ERROR_NONE;
1024 tbm_surface_queue_error_e
1025 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1026 tbm_surface_h *surfaces, int *num)
1028 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1029 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1030 TBM_RETURN_VAL_IF_FAIL(num != NULL,
1031 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1033 queue_node *node = NULL;
1034 queue_node *tmp = NULL;
1036 pthread_mutex_lock(&surface_queue->lock);
1039 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1041 surfaces[*num] = node->surface;
1046 pthread_mutex_unlock(&surface_queue->lock);
1048 return TBM_SURFACE_QUEUE_ERROR_NONE;
1055 } tbm_queue_default;
1058 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1060 tbm_queue_default *data = surface_queue->impl_data;
1062 data->num_attached = 0;
1066 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1068 tbm_queue_default *data = surface_queue->impl_data;
1070 data->num_attached = 0;
1074 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1076 free(surface_queue->impl_data);
1080 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1082 tbm_queue_default *data = surface_queue->impl_data;
1083 tbm_surface_h surface;
1085 if (data->queue_size == data->num_attached)
1088 if (surface_queue->alloc_cb) {
1089 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1090 TBM_RETURN_IF_FAIL(surface != NULL);
1091 tbm_surface_internal_ref(surface);
1093 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1094 surface_queue->height,
1095 surface_queue->format,
1097 TBM_RETURN_IF_FAIL(surface != NULL);
1100 _tbm_surface_queue_attach(surface_queue, surface);
1101 tbm_surface_internal_unref(surface);
1102 data->num_attached++;
1105 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1106 __tbm_queue_default_init,
1107 __tbm_queue_default_reset,
1108 __tbm_queue_default_destroy,
1109 __tbm_queue_default_need_attach,
1110 NULL, /*__tbm_queue_default_enqueue*/
1111 NULL, /*__tbm_queue_default_release*/
1112 NULL, /*__tbm_queue_default_dequeue*/
1113 NULL, /*__tbm_queue_default_acquire*/
1117 tbm_surface_queue_create(int queue_size, int width,
1118 int height, int format, int flags)
1120 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1121 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1122 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1123 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1125 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1126 sizeof(struct _tbm_surface_queue));
1127 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1129 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1131 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1132 sizeof(tbm_queue_default));
1134 free(surface_queue);
1138 data->queue_size = queue_size;
1139 data->flags = flags;
1140 _tbm_surface_queue_init(surface_queue,
1142 width, height, format,
1143 &tbm_queue_default_impl, data);
1145 return surface_queue;
1153 } tbm_queue_sequence;
1156 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1158 tbm_queue_sequence *data = surface_queue->impl_data;
1160 data->num_attached = 0;
1161 _queue_init(&data->dequeue_list);
1165 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1167 tbm_queue_sequence *data = surface_queue->impl_data;
1169 data->num_attached = 0;
1170 _queue_init(&data->dequeue_list);
1174 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1176 free(surface_queue->impl_data);
1180 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1182 tbm_queue_sequence *data = surface_queue->impl_data;
1183 tbm_surface_h surface;
1185 if (data->queue_size == data->num_attached)
1188 if (surface_queue->alloc_cb) {
1189 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1190 TBM_RETURN_IF_FAIL(surface != NULL);
1191 tbm_surface_internal_ref(surface);
1193 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1194 surface_queue->height,
1195 surface_queue->format,
1197 TBM_RETURN_IF_FAIL(surface != NULL);
1200 _tbm_surface_queue_attach(surface_queue, surface);
1201 tbm_surface_internal_unref(surface);
1202 data->num_attached++;
1206 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1209 tbm_queue_sequence *data = surface_queue->impl_data;
1210 queue_node *next = NULL;
1211 queue_node *tmp = NULL;
1213 node->priv_flags = 0;
1215 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1216 if (next->priv_flags)
1218 _queue_node_pop(&data->dequeue_list, next);
1219 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1224 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1227 tbm_queue_sequence *data = surface_queue->impl_data;
1228 queue_node *node = NULL;
1230 node = _tbm_surface_queue_dequeue(surface_queue);
1232 _queue_node_push_back(&data->dequeue_list, node);
1233 node->priv_flags = 1;
1239 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1240 __tbm_queue_sequence_init,
1241 __tbm_queue_sequence_reset,
1242 __tbm_queue_sequence_destroy,
1243 __tbm_queue_sequence_need_attach,
1244 __tbm_queue_sequence_enqueue,
1245 NULL, /*__tbm_queue_sequence_release*/
1246 __tbm_queue_sequence_dequeue,
1247 NULL, /*__tbm_queue_sequence_acquire*/
1251 tbm_surface_queue_sequence_create(int queue_size, int width,
1252 int height, int format, int flags)
1254 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1255 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1256 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1257 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1259 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1260 sizeof(struct _tbm_surface_queue));
1261 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1263 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1265 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1266 sizeof(tbm_queue_sequence));
1268 free(surface_queue);
1272 data->queue_size = queue_size;
1273 data->flags = flags;
1274 _tbm_surface_queue_init(surface_queue,
1276 width, height, format,
1277 &tbm_queue_sequence_impl, data);
1279 return surface_queue;
1281 /* LCOV_EXCL_STOP */