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);
678 tbm_surface_internal_dump_buffer(surface, "enqueue");
680 pthread_mutex_lock(&surface_queue->lock);
682 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
684 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
685 if (node == NULL || queue_type != NODE_LIST) {
686 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
688 pthread_mutex_unlock(&surface_queue->lock);
689 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
692 if (surface_queue->impl && surface_queue->impl->enqueue)
693 surface_queue->impl->enqueue(surface_queue, node);
695 _tbm_surface_queue_enqueue(surface_queue, node, 1);
697 if (_queue_is_empty(&surface_queue->dirty_queue)) {
698 pthread_mutex_unlock(&surface_queue->lock);
699 return TBM_SURFACE_QUEUE_ERROR_NONE;
702 node->type = QUEUE_NODE_TYPE_ENQUEUE;
704 pthread_mutex_unlock(&surface_queue->lock);
705 pthread_cond_signal(&surface_queue->dirty_cond);
707 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
709 return TBM_SURFACE_QUEUE_ERROR_NONE;
712 tbm_surface_queue_error_e
713 tbm_surface_queue_dequeue(tbm_surface_queue_h
714 surface_queue, tbm_surface_h *surface)
716 queue_node *node = NULL;
718 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
719 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
720 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
721 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
723 pthread_mutex_lock(&surface_queue->lock);
725 if (surface_queue->impl && surface_queue->impl->dequeue)
726 node = surface_queue->impl->dequeue(surface_queue);
728 node = _tbm_surface_queue_dequeue(surface_queue);
732 pthread_mutex_unlock(&surface_queue->lock);
733 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
736 if (node->surface == NULL) {
738 TBM_LOG_E("_queue_node_pop_front failed\n");
739 pthread_mutex_unlock(&surface_queue->lock);
740 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
743 node->type = QUEUE_NODE_TYPE_DEQUEUE;
744 *surface = node->surface;
746 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
748 pthread_mutex_unlock(&surface_queue->lock);
750 return TBM_SURFACE_QUEUE_ERROR_NONE;
754 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
756 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
758 pthread_mutex_lock(&surface_queue->lock);
760 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
762 if (_queue_is_empty(&surface_queue->free_queue)) {
763 if (surface_queue->impl && surface_queue->impl->need_attach)
764 surface_queue->impl->need_attach(surface_queue);
767 if (_queue_is_empty(&surface_queue->free_queue)) {
769 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
770 pthread_mutex_unlock(&surface_queue->lock);
774 pthread_mutex_unlock(&surface_queue->lock);
778 pthread_mutex_unlock(&surface_queue->lock);
783 tbm_surface_queue_error_e
784 tbm_surface_queue_release(tbm_surface_queue_h
785 surface_queue, tbm_surface_h surface)
787 queue_node *node = NULL;
790 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
791 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
792 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
793 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
795 pthread_mutex_lock(&surface_queue->lock);
797 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
799 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
800 if (node == NULL || queue_type != NODE_LIST) {
801 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
803 pthread_mutex_unlock(&surface_queue->lock);
804 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
807 if (surface_queue->impl && surface_queue->impl->release)
808 surface_queue->impl->release(surface_queue, node);
810 _tbm_surface_queue_release(surface_queue, node, 1);
812 if (_queue_is_empty(&surface_queue->free_queue)) {
813 pthread_mutex_unlock(&surface_queue->lock);
814 return TBM_SURFACE_QUEUE_ERROR_NONE;
817 node->type = QUEUE_NODE_TYPE_RELEASE;
819 pthread_mutex_unlock(&surface_queue->lock);
820 pthread_cond_signal(&surface_queue->free_cond);
822 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
824 return TBM_SURFACE_QUEUE_ERROR_NONE;
827 tbm_surface_queue_error_e
828 tbm_surface_queue_acquire(tbm_surface_queue_h
829 surface_queue, tbm_surface_h *surface)
831 queue_node *node = NULL;
833 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
834 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
835 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
836 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
838 pthread_mutex_lock(&surface_queue->lock);
840 if (surface_queue->impl && surface_queue->impl->acquire)
841 node = surface_queue->impl->acquire(surface_queue);
843 node = _tbm_surface_queue_acquire(surface_queue);
847 pthread_mutex_unlock(&surface_queue->lock);
848 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
851 if (node->surface == NULL) {
853 TBM_LOG_E("_queue_node_pop_front failed\n");
854 pthread_mutex_unlock(&surface_queue->lock);
855 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
858 node->type = QUEUE_NODE_TYPE_ACQUIRE;
860 *surface = node->surface;
862 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
864 pthread_mutex_unlock(&surface_queue->lock);
867 tbm_surface_internal_dump_buffer(*surface, "acquire");
869 return TBM_SURFACE_QUEUE_ERROR_NONE;
873 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
875 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
877 pthread_mutex_lock(&surface_queue->lock);
879 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
881 if (_queue_is_empty(&surface_queue->dirty_queue)) {
883 if (!_queue_has_node_type(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
884 TBM_LOG_E("Deosn't have dequeue type node\n");
885 pthread_mutex_unlock(&surface_queue->lock);
889 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
890 pthread_mutex_unlock(&surface_queue->lock);
894 pthread_mutex_unlock(&surface_queue->lock);
898 pthread_mutex_unlock(&surface_queue->lock);
904 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
906 queue_node *node = NULL, *tmp = NULL;
908 TBM_RETURN_IF_FAIL(surface_queue != NULL);
910 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
912 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
913 _queue_delete_node(surface_queue, node);
916 _notify_emit(surface_queue, &surface_queue->destory_noti);
918 if (surface_queue->impl && surface_queue->impl->destroy)
919 surface_queue->impl->destroy(surface_queue);
921 _notify_remove_all(&surface_queue->destory_noti);
922 _notify_remove_all(&surface_queue->acquirable_noti);
923 _notify_remove_all(&surface_queue->dequeuable_noti);
924 _notify_remove_all(&surface_queue->reset_noti);
926 pthread_mutex_destroy(&surface_queue->lock);
930 tbm_surface_queue_error_e
931 tbm_surface_queue_reset(tbm_surface_queue_h
932 surface_queue, int width, int height, int format)
934 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
935 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
937 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
939 queue_node *node = NULL, *tmp = NULL;
941 if (width == surface_queue->width && height == surface_queue->height &&
942 format == surface_queue->format)
943 return TBM_SURFACE_QUEUE_ERROR_NONE;
945 pthread_mutex_lock(&surface_queue->lock);
947 surface_queue->width = width;
948 surface_queue->height = height;
949 surface_queue->format = format;
951 /* Destory surface and Push to free_queue */
952 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
953 _queue_delete_node(surface_queue, node);
957 _queue_init(&surface_queue->free_queue);
958 _queue_init(&surface_queue->dirty_queue);
959 LIST_INITHEAD(&surface_queue->list);
961 if (surface_queue->impl && surface_queue->impl->reset)
962 surface_queue->impl->reset(surface_queue);
964 pthread_mutex_unlock(&surface_queue->lock);
965 pthread_cond_signal(&surface_queue->free_cond);
967 _notify_emit(surface_queue, &surface_queue->reset_noti);
969 return TBM_SURFACE_QUEUE_ERROR_NONE;
972 tbm_surface_queue_error_e
973 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
975 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
976 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
978 queue_node *node = NULL, *tmp = NULL;
980 pthread_mutex_lock(&surface_queue->lock);
982 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
984 /* Destory surface and Push to free_queue */
985 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
986 _queue_delete_node(surface_queue, node);
990 _queue_init(&surface_queue->free_queue);
991 _queue_init(&surface_queue->dirty_queue);
992 LIST_INITHEAD(&surface_queue->list);
994 if (surface_queue->impl && surface_queue->impl->reset)
995 surface_queue->impl->reset(surface_queue);
997 _notify_emit(surface_queue, &surface_queue->reset_noti);
999 pthread_mutex_unlock(&surface_queue->lock);
1000 pthread_cond_signal(&surface_queue->free_cond);
1002 return TBM_SURFACE_QUEUE_ERROR_NONE;
1005 tbm_surface_queue_error_e
1006 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1007 tbm_surface_h *surfaces, int *num)
1009 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1010 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1011 TBM_RETURN_VAL_IF_FAIL(num != NULL,
1012 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1014 queue_node *node = NULL;
1015 queue_node *tmp = NULL;
1017 pthread_mutex_lock(&surface_queue->lock);
1020 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1022 surfaces[*num] = node->surface;
1027 pthread_mutex_unlock(&surface_queue->lock);
1029 return TBM_SURFACE_QUEUE_ERROR_NONE;
1036 } tbm_queue_default;
1039 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1041 tbm_queue_default *data = surface_queue->impl_data;
1043 data->num_attached = 0;
1047 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1049 tbm_queue_default *data = surface_queue->impl_data;
1051 data->num_attached = 0;
1055 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1057 free(surface_queue->impl_data);
1061 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1063 tbm_queue_default *data = surface_queue->impl_data;
1064 tbm_surface_h surface;
1066 if (data->queue_size == data->num_attached)
1069 if (surface_queue->alloc_cb) {
1070 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1071 TBM_RETURN_IF_FAIL(surface != NULL);
1072 tbm_surface_internal_ref(surface);
1074 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1075 surface_queue->height,
1076 surface_queue->format,
1078 TBM_RETURN_IF_FAIL(surface != NULL);
1081 _tbm_surface_queue_attach(surface_queue, surface);
1082 tbm_surface_internal_unref(surface);
1083 data->num_attached++;
1086 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1087 __tbm_queue_default_init,
1088 __tbm_queue_default_reset,
1089 __tbm_queue_default_destroy,
1090 __tbm_queue_default_need_attach,
1091 NULL, /*__tbm_queue_default_enqueue*/
1092 NULL, /*__tbm_queue_default_release*/
1093 NULL, /*__tbm_queue_default_dequeue*/
1094 NULL, /*__tbm_queue_default_acquire*/
1098 tbm_surface_queue_create(int queue_size, int width,
1099 int height, int format, int flags)
1101 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1102 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1103 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1104 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1106 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1107 sizeof(struct _tbm_surface_queue));
1108 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1110 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1112 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1113 sizeof(tbm_queue_default));
1115 free(surface_queue);
1119 data->queue_size = queue_size;
1120 data->flags = flags;
1121 _tbm_surface_queue_init(surface_queue,
1123 width, height, format,
1124 &tbm_queue_default_impl, data);
1126 return surface_queue;
1134 } tbm_queue_sequence;
1137 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1139 tbm_queue_sequence *data = surface_queue->impl_data;
1141 data->num_attached = 0;
1142 _queue_init(&data->dequeue_list);
1146 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1148 tbm_queue_sequence *data = surface_queue->impl_data;
1150 data->num_attached = 0;
1151 _queue_init(&data->dequeue_list);
1155 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1157 free(surface_queue->impl_data);
1161 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1163 tbm_queue_sequence *data = surface_queue->impl_data;
1164 tbm_surface_h surface;
1166 if (data->queue_size == data->num_attached)
1169 if (surface_queue->alloc_cb) {
1170 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1171 TBM_RETURN_IF_FAIL(surface != NULL);
1172 tbm_surface_internal_ref(surface);
1174 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1175 surface_queue->height,
1176 surface_queue->format,
1178 TBM_RETURN_IF_FAIL(surface != NULL);
1181 _tbm_surface_queue_attach(surface_queue, surface);
1182 tbm_surface_internal_unref(surface);
1183 data->num_attached++;
1187 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1190 tbm_queue_sequence *data = surface_queue->impl_data;
1191 queue_node *next = NULL;
1192 queue_node *tmp = NULL;
1194 node->priv_flags = 0;
1196 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1197 if (next->priv_flags)
1199 _queue_node_pop(&data->dequeue_list, next);
1200 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1205 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1208 tbm_queue_sequence *data = surface_queue->impl_data;
1209 queue_node *node = NULL;
1211 node = _tbm_surface_queue_dequeue(surface_queue);
1213 _queue_node_push_back(&data->dequeue_list, node);
1214 node->priv_flags = 1;
1220 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1221 __tbm_queue_sequence_init,
1222 __tbm_queue_sequence_reset,
1223 __tbm_queue_sequence_destroy,
1224 __tbm_queue_sequence_need_attach,
1225 __tbm_queue_sequence_enqueue,
1226 NULL, /*__tbm_queue_sequence_release*/
1227 __tbm_queue_sequence_dequeue,
1228 NULL, /*__tbm_queue_sequence_acquire*/
1232 tbm_surface_queue_sequence_create(int queue_size, int width,
1233 int height, int format, int flags)
1235 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1236 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1237 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1238 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1240 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1241 sizeof(struct _tbm_surface_queue));
1242 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1244 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1246 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1247 sizeof(tbm_queue_sequence));
1249 free(surface_queue);
1253 data->queue_size = queue_size;
1254 data->flags = flags;
1255 _tbm_surface_queue_init(surface_queue,
1257 width, height, format,
1258 &tbm_queue_sequence_impl, data);
1260 return surface_queue;
1262 /* LCOV_EXCL_STOP */