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_attach(tbm_surface_queue_h surface_queue,
336 tbm_surface_h surface)
338 queue_node *node = NULL;
340 node = _queue_node_create();
341 TBM_RETURN_IF_FAIL(node != NULL);
343 tbm_surface_internal_ref(surface);
344 node->surface = surface;
346 LIST_ADDTAIL(&node->link, &surface_queue->list);
347 _queue_node_push_back(&surface_queue->free_queue, node);
351 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
352 tbm_surface_h surface)
354 queue_node *node = NULL;
357 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
359 _queue_delete_node(surface_queue, node);
363 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
364 queue_node *node, int push_back)
367 _queue_node_push_back(&surface_queue->dirty_queue, node);
369 _queue_node_push_front(&surface_queue->dirty_queue, node);
373 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
375 queue_node *node = NULL;
377 if (_queue_is_empty(&surface_queue->free_queue)) {
378 if (surface_queue->impl && surface_queue->impl->need_attach)
379 surface_queue->impl->need_attach(surface_queue);
381 if (_queue_is_empty(&surface_queue->free_queue))
385 node = _queue_node_pop_front(&surface_queue->free_queue);
391 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
393 queue_node *node = NULL;
395 if (_queue_is_empty(&surface_queue->dirty_queue))
398 node = _queue_node_pop_front(&surface_queue->dirty_queue);
404 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
405 queue_node *node, int push_back)
408 _queue_node_push_back(&surface_queue->free_queue, node);
410 _queue_node_push_front(&surface_queue->free_queue, node);
414 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
416 int width, int height, int format,
417 const tbm_surface_queue_interface *impl, void *data)
419 TBM_RETURN_IF_FAIL(surface_queue != NULL);
420 TBM_RETURN_IF_FAIL(impl != NULL);
422 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
424 pthread_mutex_init(&surface_queue->lock, NULL);
425 pthread_cond_init(&surface_queue->free_cond, NULL);
426 pthread_cond_init(&surface_queue->dirty_cond, NULL);
428 surface_queue->queue_size = queue_size;
429 surface_queue->width = width;
430 surface_queue->height = height;
431 surface_queue->format = format;
432 surface_queue->impl = impl;
433 surface_queue->impl_data = data;
435 _queue_init(&surface_queue->free_queue);
436 _queue_init(&surface_queue->dirty_queue);
437 LIST_INITHEAD(&surface_queue->list);
439 LIST_INITHEAD(&surface_queue->destory_noti);
440 LIST_INITHEAD(&surface_queue->acquirable_noti);
441 LIST_INITHEAD(&surface_queue->dequeuable_noti);
442 LIST_INITHEAD(&surface_queue->reset_noti);
444 if (surface_queue->impl && surface_queue->impl->init)
445 surface_queue->impl->init(surface_queue);
448 tbm_surface_queue_error_e
449 tbm_surface_queue_add_destroy_cb(
450 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
453 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
454 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
456 pthread_mutex_lock(&surface_queue->lock);
458 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
460 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
462 pthread_mutex_unlock(&surface_queue->lock);
464 return TBM_SURFACE_QUEUE_ERROR_NONE;
467 tbm_surface_queue_error_e
468 tbm_surface_queue_remove_destroy_cb(
469 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
472 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
473 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
475 pthread_mutex_lock(&surface_queue->lock);
477 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
479 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
481 pthread_mutex_unlock(&surface_queue->lock);
483 return TBM_SURFACE_QUEUE_ERROR_NONE;
486 tbm_surface_queue_error_e
487 tbm_surface_queue_add_dequeuable_cb(
488 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
491 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
492 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
494 pthread_mutex_lock(&surface_queue->lock);
496 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
498 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
500 pthread_mutex_unlock(&surface_queue->lock);
502 return TBM_SURFACE_QUEUE_ERROR_NONE;
505 tbm_surface_queue_error_e
506 tbm_surface_queue_remove_dequeuable_cb(
507 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
510 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
511 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
513 pthread_mutex_lock(&surface_queue->lock);
515 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
517 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
519 pthread_mutex_unlock(&surface_queue->lock);
521 return TBM_SURFACE_QUEUE_ERROR_NONE;
524 tbm_surface_queue_error_e
525 tbm_surface_queue_add_acquirable_cb(
526 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
529 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
530 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
532 pthread_mutex_lock(&surface_queue->lock);
534 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
536 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
538 pthread_mutex_unlock(&surface_queue->lock);
540 return TBM_SURFACE_QUEUE_ERROR_NONE;
543 tbm_surface_queue_error_e
544 tbm_surface_queue_remove_acquirable_cb(
545 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
548 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
549 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
551 pthread_mutex_lock(&surface_queue->lock);
553 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
555 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
557 pthread_mutex_unlock(&surface_queue->lock);
559 return TBM_SURFACE_QUEUE_ERROR_NONE;
562 tbm_surface_queue_error_e
563 tbm_surface_queue_set_alloc_cb(
564 tbm_surface_queue_h surface_queue,
565 tbm_surface_alloc_cb alloc_cb,
566 tbm_surface_free_cb free_cb,
569 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
570 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
572 pthread_mutex_lock(&surface_queue->lock);
574 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
576 surface_queue->alloc_cb = alloc_cb;
577 surface_queue->free_cb = free_cb;
578 surface_queue->alloc_cb_data = data;
580 pthread_mutex_unlock(&surface_queue->lock);
582 return TBM_SURFACE_QUEUE_ERROR_NONE;
586 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
588 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
590 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
592 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
594 return surface_queue->width;
598 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
600 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
602 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
604 return surface_queue->height;
608 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
610 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
612 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
614 return surface_queue->format;
618 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
620 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
622 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
624 return surface_queue->queue_size;
627 tbm_surface_queue_error_e
628 tbm_surface_queue_add_reset_cb(
629 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
632 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
633 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
635 pthread_mutex_lock(&surface_queue->lock);
637 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
639 _notify_add(&surface_queue->reset_noti, reset_cb, data);
641 pthread_mutex_unlock(&surface_queue->lock);
643 return TBM_SURFACE_QUEUE_ERROR_NONE;
646 tbm_surface_queue_error_e
647 tbm_surface_queue_remove_reset_cb(
648 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
651 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
652 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
654 pthread_mutex_lock(&surface_queue->lock);
656 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
658 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
660 pthread_mutex_unlock(&surface_queue->lock);
662 return TBM_SURFACE_QUEUE_ERROR_NONE;
665 tbm_surface_queue_error_e
666 tbm_surface_queue_enqueue(tbm_surface_queue_h
667 surface_queue, tbm_surface_h surface)
669 queue_node *node = NULL;
672 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
673 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
674 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
675 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
677 pthread_mutex_lock(&surface_queue->lock);
679 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
681 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
682 if (node == NULL || queue_type != NODE_LIST) {
683 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
685 pthread_mutex_unlock(&surface_queue->lock);
686 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
689 if (surface_queue->impl && surface_queue->impl->enqueue)
690 surface_queue->impl->enqueue(surface_queue, node);
692 _tbm_surface_queue_enqueue(surface_queue, node, 1);
694 if (_queue_is_empty(&surface_queue->dirty_queue)) {
695 pthread_mutex_unlock(&surface_queue->lock);
696 return TBM_SURFACE_QUEUE_ERROR_NONE;
699 node->type = QUEUE_NODE_TYPE_ENQUEUE;
701 pthread_mutex_unlock(&surface_queue->lock);
702 pthread_cond_signal(&surface_queue->dirty_cond);
704 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
706 return TBM_SURFACE_QUEUE_ERROR_NONE;
709 tbm_surface_queue_error_e
710 tbm_surface_queue_dequeue(tbm_surface_queue_h
711 surface_queue, tbm_surface_h *surface)
713 queue_node *node = NULL;
715 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
716 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
717 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
718 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
720 pthread_mutex_lock(&surface_queue->lock);
722 if (surface_queue->impl && surface_queue->impl->dequeue)
723 node = surface_queue->impl->dequeue(surface_queue);
725 node = _tbm_surface_queue_dequeue(surface_queue);
729 pthread_mutex_unlock(&surface_queue->lock);
730 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
733 if (node->surface == NULL) {
735 TBM_LOG_E("_queue_node_pop_front failed\n");
736 pthread_mutex_unlock(&surface_queue->lock);
737 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
740 node->type = QUEUE_NODE_TYPE_DEQUEUE;
741 *surface = node->surface;
743 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
745 pthread_mutex_unlock(&surface_queue->lock);
747 return TBM_SURFACE_QUEUE_ERROR_NONE;
751 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
753 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
755 pthread_mutex_lock(&surface_queue->lock);
757 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
759 if (_queue_is_empty(&surface_queue->free_queue)) {
760 if (surface_queue->impl && surface_queue->impl->need_attach)
761 surface_queue->impl->need_attach(surface_queue);
764 if (_queue_is_empty(&surface_queue->free_queue)) {
766 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
767 pthread_mutex_unlock(&surface_queue->lock);
771 pthread_mutex_unlock(&surface_queue->lock);
775 pthread_mutex_unlock(&surface_queue->lock);
780 tbm_surface_queue_error_e
781 tbm_surface_queue_release(tbm_surface_queue_h
782 surface_queue, tbm_surface_h surface)
784 queue_node *node = NULL;
787 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
788 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
789 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
790 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
792 pthread_mutex_lock(&surface_queue->lock);
794 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
796 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
797 if (node == NULL || queue_type != NODE_LIST) {
798 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
800 pthread_mutex_unlock(&surface_queue->lock);
801 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
804 if (surface_queue->impl && surface_queue->impl->release)
805 surface_queue->impl->release(surface_queue, node);
807 _tbm_surface_queue_release(surface_queue, node, 1);
809 if (_queue_is_empty(&surface_queue->free_queue)) {
810 pthread_mutex_unlock(&surface_queue->lock);
811 return TBM_SURFACE_QUEUE_ERROR_NONE;
814 node->type = QUEUE_NODE_TYPE_RELEASE;
816 pthread_mutex_unlock(&surface_queue->lock);
817 pthread_cond_signal(&surface_queue->free_cond);
819 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
821 return TBM_SURFACE_QUEUE_ERROR_NONE;
824 tbm_surface_queue_error_e
825 tbm_surface_queue_acquire(tbm_surface_queue_h
826 surface_queue, tbm_surface_h *surface)
828 queue_node *node = NULL;
830 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
831 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
832 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
833 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
835 pthread_mutex_lock(&surface_queue->lock);
837 if (surface_queue->impl && surface_queue->impl->acquire)
838 node = surface_queue->impl->acquire(surface_queue);
840 node = _tbm_surface_queue_acquire(surface_queue);
844 pthread_mutex_unlock(&surface_queue->lock);
845 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
848 if (node->surface == NULL) {
850 TBM_LOG_E("_queue_node_pop_front failed\n");
851 pthread_mutex_unlock(&surface_queue->lock);
852 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
855 node->type = QUEUE_NODE_TYPE_ACQUIRE;
857 *surface = node->surface;
859 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
861 pthread_mutex_unlock(&surface_queue->lock);
863 return TBM_SURFACE_QUEUE_ERROR_NONE;
867 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
869 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
871 pthread_mutex_lock(&surface_queue->lock);
873 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
875 if (_queue_is_empty(&surface_queue->dirty_queue)) {
877 if (!_queue_has_node_type(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
878 TBM_LOG_E("Deosn't have dequeue type node\n");
879 pthread_mutex_unlock(&surface_queue->lock);
883 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
884 pthread_mutex_unlock(&surface_queue->lock);
888 pthread_mutex_unlock(&surface_queue->lock);
892 pthread_mutex_unlock(&surface_queue->lock);
898 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
900 queue_node *node = NULL, *tmp = NULL;
902 TBM_RETURN_IF_FAIL(surface_queue != NULL);
904 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
906 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
907 _queue_delete_node(surface_queue, node);
910 _notify_emit(surface_queue, &surface_queue->destory_noti);
912 if (surface_queue->impl && surface_queue->impl->destroy)
913 surface_queue->impl->destroy(surface_queue);
915 _notify_remove_all(&surface_queue->destory_noti);
916 _notify_remove_all(&surface_queue->acquirable_noti);
917 _notify_remove_all(&surface_queue->dequeuable_noti);
918 _notify_remove_all(&surface_queue->reset_noti);
920 pthread_mutex_destroy(&surface_queue->lock);
924 tbm_surface_queue_error_e
925 tbm_surface_queue_reset(tbm_surface_queue_h
926 surface_queue, int width, int height, int format)
928 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
929 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
931 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
933 queue_node *node = NULL, *tmp = NULL;
935 if (width == surface_queue->width && height == surface_queue->height &&
936 format == surface_queue->format)
937 return TBM_SURFACE_QUEUE_ERROR_NONE;
939 pthread_mutex_lock(&surface_queue->lock);
941 surface_queue->width = width;
942 surface_queue->height = height;
943 surface_queue->format = format;
945 /* Destory surface and Push to free_queue */
946 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
947 _queue_delete_node(surface_queue, node);
951 _queue_init(&surface_queue->free_queue);
952 _queue_init(&surface_queue->dirty_queue);
953 LIST_INITHEAD(&surface_queue->list);
955 if (surface_queue->impl && surface_queue->impl->reset)
956 surface_queue->impl->reset(surface_queue);
958 pthread_mutex_unlock(&surface_queue->lock);
959 pthread_cond_signal(&surface_queue->free_cond);
961 _notify_emit(surface_queue, &surface_queue->reset_noti);
963 return TBM_SURFACE_QUEUE_ERROR_NONE;
966 tbm_surface_queue_error_e
967 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
969 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
970 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
972 queue_node *node = NULL, *tmp = NULL;
974 pthread_mutex_lock(&surface_queue->lock);
976 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
978 /* Destory surface and Push to free_queue */
979 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
980 _queue_delete_node(surface_queue, node);
984 _queue_init(&surface_queue->free_queue);
985 _queue_init(&surface_queue->dirty_queue);
986 LIST_INITHEAD(&surface_queue->list);
988 if (surface_queue->impl && surface_queue->impl->reset)
989 surface_queue->impl->reset(surface_queue);
991 _notify_emit(surface_queue, &surface_queue->reset_noti);
993 pthread_mutex_unlock(&surface_queue->lock);
994 pthread_cond_signal(&surface_queue->free_cond);
996 return TBM_SURFACE_QUEUE_ERROR_NONE;
999 tbm_surface_queue_error_e
1000 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1001 tbm_surface_h *surfaces, int *num)
1003 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1004 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1005 TBM_RETURN_VAL_IF_FAIL(num != NULL,
1006 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1008 queue_node *node = NULL;
1009 queue_node *tmp = NULL;
1011 pthread_mutex_lock(&surface_queue->lock);
1014 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1016 surfaces[*num] = node->surface;
1021 pthread_mutex_unlock(&surface_queue->lock);
1023 return TBM_SURFACE_QUEUE_ERROR_NONE;
1030 } tbm_queue_default;
1033 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1035 tbm_queue_default *data = surface_queue->impl_data;
1037 data->num_attached = 0;
1041 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1043 tbm_queue_default *data = surface_queue->impl_data;
1045 data->num_attached = 0;
1049 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1051 free(surface_queue->impl_data);
1055 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1057 tbm_queue_default *data = surface_queue->impl_data;
1058 tbm_surface_h surface;
1060 if (data->queue_size == data->num_attached)
1063 if (surface_queue->alloc_cb) {
1064 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1065 TBM_RETURN_IF_FAIL(surface != NULL);
1066 tbm_surface_internal_ref(surface);
1068 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1069 surface_queue->height,
1070 surface_queue->format,
1072 TBM_RETURN_IF_FAIL(surface != NULL);
1075 _tbm_surface_queue_attach(surface_queue, surface);
1076 tbm_surface_internal_unref(surface);
1077 data->num_attached++;
1080 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1081 __tbm_queue_default_init,
1082 __tbm_queue_default_reset,
1083 __tbm_queue_default_destroy,
1084 __tbm_queue_default_need_attach,
1085 NULL, /*__tbm_queue_default_enqueue*/
1086 NULL, /*__tbm_queue_default_release*/
1087 NULL, /*__tbm_queue_default_dequeue*/
1088 NULL, /*__tbm_queue_default_acquire*/
1092 tbm_surface_queue_create(int queue_size, int width,
1093 int height, int format, int flags)
1095 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1096 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1097 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1098 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1100 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1101 sizeof(struct _tbm_surface_queue));
1102 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1104 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1106 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1107 sizeof(tbm_queue_default));
1109 free(surface_queue);
1113 data->queue_size = queue_size;
1114 data->flags = flags;
1115 _tbm_surface_queue_init(surface_queue,
1117 width, height, format,
1118 &tbm_queue_default_impl, data);
1120 return surface_queue;
1128 } tbm_queue_sequence;
1131 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1133 tbm_queue_sequence *data = surface_queue->impl_data;
1135 data->num_attached = 0;
1136 _queue_init(&data->dequeue_list);
1140 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1142 tbm_queue_sequence *data = surface_queue->impl_data;
1144 data->num_attached = 0;
1145 _queue_init(&data->dequeue_list);
1149 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1151 free(surface_queue->impl_data);
1155 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1157 tbm_queue_sequence *data = surface_queue->impl_data;
1158 tbm_surface_h surface;
1160 if (data->queue_size == data->num_attached)
1163 if (surface_queue->alloc_cb) {
1164 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1165 TBM_RETURN_IF_FAIL(surface != NULL);
1166 tbm_surface_internal_ref(surface);
1168 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1169 surface_queue->height,
1170 surface_queue->format,
1172 TBM_RETURN_IF_FAIL(surface != NULL);
1175 _tbm_surface_queue_attach(surface_queue, surface);
1176 tbm_surface_internal_unref(surface);
1177 data->num_attached++;
1181 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1184 tbm_queue_sequence *data = surface_queue->impl_data;
1185 queue_node *next = NULL;
1186 queue_node *tmp = NULL;
1188 node->priv_flags = 0;
1190 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1191 if (next->priv_flags)
1193 _queue_node_pop(&data->dequeue_list, next);
1194 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1199 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1202 tbm_queue_sequence *data = surface_queue->impl_data;
1203 queue_node *node = NULL;
1205 node = _tbm_surface_queue_dequeue(surface_queue);
1207 _queue_node_push_back(&data->dequeue_list, node);
1208 node->priv_flags = 1;
1214 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1215 __tbm_queue_sequence_init,
1216 __tbm_queue_sequence_reset,
1217 __tbm_queue_sequence_destroy,
1218 __tbm_queue_sequence_need_attach,
1219 __tbm_queue_sequence_enqueue,
1220 NULL, /*__tbm_queue_sequence_release*/
1221 __tbm_queue_sequence_dequeue,
1222 NULL, /*__tbm_queue_sequence_acquire*/
1226 tbm_surface_queue_sequence_create(int queue_size, int width,
1227 int height, int format, int flags)
1229 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1230 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1231 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1232 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1234 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1235 sizeof(struct _tbm_surface_queue));
1236 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1238 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1240 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1241 sizeof(tbm_queue_sequence));
1243 free(surface_queue);
1247 data->queue_size = queue_size;
1248 data->flags = flags;
1249 _tbm_surface_queue_init(surface_queue,
1251 width, height, format,
1252 &tbm_queue_sequence_impl, data);
1254 return surface_queue;
1256 /* LCOV_EXCL_STOP */