1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
32 #include "tbm_bufmgr_int.h"
42 #define TBM_TRACE() TBM_LOG("[TRACE] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
52 struct list_head head;
53 struct list_head tail;
59 tbm_surface_h surface;
61 struct list_head item_link;
62 struct list_head link;
64 unsigned int priv_flags; /*for each queue*/
68 struct list_head link;
70 tbm_surface_queue_notify_cb cb;
74 typedef struct _tbm_surface_queue_interface {
75 void (*init)(tbm_surface_queue_h queue);
76 void (*reset)(tbm_surface_queue_h queue);
77 void (*destroy)(tbm_surface_queue_h queue);
78 void (*need_attach)(tbm_surface_queue_h queue);
80 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
81 void (*release)(tbm_surface_queue_h queue, queue_node *node);
82 queue_node *(*dequeue)(tbm_surface_queue_h queue);
83 queue_node *(*acquire)(tbm_surface_queue_h queue);
84 } tbm_surface_queue_interface;
86 struct _tbm_surface_queue {
93 struct list_head list;
95 struct list_head destory_noti;
96 struct list_head dequeuable_noti;
97 struct list_head acquirable_noti;
98 struct list_head reset_noti;
100 tbm_surface_queue_notify_cb destroy_cb;
101 void *destroy_cb_data;
103 tbm_surface_queue_notify_cb dequeuable_cb;
104 void *dequeuable_cb_data;
106 tbm_surface_queue_notify_cb acquirable_cb;
107 void *acquirable_cb_data;
109 tbm_surface_queue_notify_cb reset_cb;
112 pthread_mutex_t lock;
113 pthread_cond_t free_cond;
114 pthread_cond_t dirty_cond;
116 const tbm_surface_queue_interface *impl;
119 //For external buffer allocation
120 tbm_surface_alloc_cb alloc_cb;
121 tbm_surface_free_cb free_cb;
126 _queue_node_create(void)
128 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
130 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
136 _queue_node_delete(queue_node *node)
138 LIST_DEL(&node->item_link);
139 LIST_DEL(&node->link);
144 _queue_is_empty(queue *queue)
146 if (queue->head.next == &queue->tail)
153 _queue_node_push_back(queue *queue, queue_node *node)
155 LIST_ADDTAIL(&node->item_link, &queue->tail);
160 _queue_node_push_front(queue *queue, queue_node *node)
162 LIST_ADD(&node->item_link, &queue->head);
167 _queue_node_pop_front(queue *queue)
169 queue_node *node = NULL;
171 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
173 LIST_DEL(&node->item_link);
180 _queue_node_pop(queue *queue, queue_node *node)
182 LIST_DEL(&node->item_link);
189 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
190 tbm_surface_h surface, int *out_type)
192 queue_node *node = NULL;
193 queue_node *tmp = NULL;
196 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
200 if (type & FREE_QUEUE) {
201 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
203 if (node->surface == surface) {
205 *out_type = FREE_QUEUE;
212 if (type & DIRTY_QUEUE) {
213 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
215 if (node->surface == surface) {
217 *out_type = DIRTY_QUEUE;
224 if (type & NODE_LIST) {
225 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
226 if (node->surface == surface) {
228 *out_type = NODE_LIST;
239 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
242 if (surface_queue->free_cb) {
243 surface_queue->free_cb(surface_queue,
244 surface_queue->alloc_cb_data,
247 tbm_surface_destroy(node->surface);
251 _queue_node_delete(node);
255 _queue_init(queue *queue)
257 LIST_INITHEAD(&queue->head);
258 LIST_INITHEAD(&queue->tail);
259 LIST_ADDTAIL(&queue->head, &queue->tail);
264 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
267 TBM_RETURN_IF_FAIL(cb != NULL);
269 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
271 TBM_RETURN_IF_FAIL(item != NULL);
273 LIST_INITHEAD(&item->link);
277 LIST_ADDTAIL(&item->link, list);
281 _notify_remove(struct list_head *list,
282 tbm_surface_queue_notify_cb cb, void *data)
284 queue_notify *item = NULL, *tmp = NULL;
286 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
287 if (item->cb == cb && item->data == data) {
288 LIST_DEL(&item->link);
294 TBM_LOG("Cannot find notifiy\n");
298 _notify_remove_all(struct list_head *list)
300 queue_notify *item = NULL, *tmp = NULL;
302 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
303 LIST_DEL(&item->link);
309 _notify_emit(tbm_surface_queue_h surface_queue,
310 struct list_head *list)
312 queue_notify *item = NULL, *tmp = NULL;
314 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
315 item->cb(surface_queue, item->data);
320 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
321 tbm_surface_h surface)
323 queue_node *node = NULL;
325 node = _queue_node_create();
326 TBM_RETURN_IF_FAIL(node != NULL);
328 tbm_surface_internal_ref(surface);
329 node->surface = surface;
331 LIST_ADDTAIL(&node->link, &surface_queue->list);
332 _queue_node_push_back(&surface_queue->free_queue, node);
336 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
337 tbm_surface_h surface)
339 queue_node *node = NULL;
342 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
344 _queue_delete_node(surface_queue, node);
348 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
349 queue_node *node, int push_back)
352 _queue_node_push_back(&surface_queue->dirty_queue, node);
354 _queue_node_push_front(&surface_queue->dirty_queue, node);
358 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
360 queue_node *node = NULL;
362 if (_queue_is_empty(&surface_queue->free_queue)) {
363 if (surface_queue->impl && surface_queue->impl->need_attach)
364 surface_queue->impl->need_attach(surface_queue);
366 if (_queue_is_empty(&surface_queue->free_queue))
370 node = _queue_node_pop_front(&surface_queue->free_queue);
376 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
378 queue_node *node = NULL;
380 if (_queue_is_empty(&surface_queue->dirty_queue))
383 node = _queue_node_pop_front(&surface_queue->dirty_queue);
389 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
390 queue_node *node, int push_back)
393 _queue_node_push_back(&surface_queue->free_queue, node);
395 _queue_node_push_front(&surface_queue->free_queue, node);
399 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
400 int width, int height, int format,
401 const tbm_surface_queue_interface *impl, void *data)
403 TBM_RETURN_IF_FAIL(surface_queue != NULL);
404 TBM_RETURN_IF_FAIL(impl != NULL);
406 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
408 pthread_mutex_init(&surface_queue->lock, NULL);
409 pthread_cond_init(&surface_queue->free_cond, NULL);
410 pthread_cond_init(&surface_queue->dirty_cond, NULL);
412 surface_queue->width = width;
413 surface_queue->height = height;
414 surface_queue->format = format;
415 surface_queue->impl = impl;
416 surface_queue->impl_data = data;
418 _queue_init(&surface_queue->free_queue);
419 _queue_init(&surface_queue->dirty_queue);
420 LIST_INITHEAD(&surface_queue->list);
422 LIST_INITHEAD(&surface_queue->destory_noti);
423 LIST_INITHEAD(&surface_queue->acquirable_noti);
424 LIST_INITHEAD(&surface_queue->dequeuable_noti);
425 LIST_INITHEAD(&surface_queue->reset_noti);
427 if (surface_queue->impl && surface_queue->impl->init)
428 surface_queue->impl->init(surface_queue);
431 tbm_surface_queue_error_e
432 tbm_surface_queue_set_destroy_cb(
433 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
436 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
437 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
439 pthread_mutex_lock(&surface_queue->lock);
441 surface_queue->destroy_cb = destroy_cb;
442 surface_queue->destroy_cb_data = data;
444 pthread_mutex_unlock(&surface_queue->lock);
446 return TBM_SURFACE_QUEUE_ERROR_NONE;
449 tbm_surface_queue_error_e
450 tbm_surface_queue_add_destroy_cb(
451 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
454 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
455 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
457 pthread_mutex_lock(&surface_queue->lock);
459 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
461 pthread_mutex_unlock(&surface_queue->lock);
463 return TBM_SURFACE_QUEUE_ERROR_NONE;
466 tbm_surface_queue_error_e
467 tbm_surface_queue_remove_destroy_cb(
468 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
471 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
472 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
474 pthread_mutex_lock(&surface_queue->lock);
476 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
478 pthread_mutex_unlock(&surface_queue->lock);
480 return TBM_SURFACE_QUEUE_ERROR_NONE;
483 tbm_surface_queue_error_e
484 tbm_surface_queue_set_dequeuable_cb(
485 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
488 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
489 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
491 pthread_mutex_lock(&surface_queue->lock);
493 surface_queue->dequeuable_cb = dequeuable_cb;
494 surface_queue->dequeuable_cb_data = 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 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
513 pthread_mutex_unlock(&surface_queue->lock);
515 return TBM_SURFACE_QUEUE_ERROR_NONE;
518 tbm_surface_queue_error_e
519 tbm_surface_queue_remove_dequeuable_cb(
520 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
523 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
524 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
526 pthread_mutex_lock(&surface_queue->lock);
528 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
530 pthread_mutex_unlock(&surface_queue->lock);
532 return TBM_SURFACE_QUEUE_ERROR_NONE;
535 tbm_surface_queue_error_e
536 tbm_surface_queue_set_acquirable_cb(
537 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
540 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
541 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
543 pthread_mutex_lock(&surface_queue->lock);
545 surface_queue->acquirable_cb = acquirable_cb;
546 surface_queue->acquirable_cb_data = data;
548 pthread_mutex_unlock(&surface_queue->lock);
550 return TBM_SURFACE_QUEUE_ERROR_NONE;
553 tbm_surface_queue_error_e
554 tbm_surface_queue_add_acquirable_cb(
555 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
558 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
559 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
561 pthread_mutex_lock(&surface_queue->lock);
563 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
565 pthread_mutex_unlock(&surface_queue->lock);
567 return TBM_SURFACE_QUEUE_ERROR_NONE;
570 tbm_surface_queue_error_e
571 tbm_surface_queue_remove_acquirable_cb(
572 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
575 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
576 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
578 pthread_mutex_lock(&surface_queue->lock);
580 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
582 pthread_mutex_unlock(&surface_queue->lock);
584 return TBM_SURFACE_QUEUE_ERROR_NONE;
587 tbm_surface_queue_error_e
588 tbm_surface_queue_set_alloc_cb(
589 tbm_surface_queue_h surface_queue,
590 tbm_surface_alloc_cb alloc_cb,
591 tbm_surface_free_cb free_cb,
594 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
595 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
597 pthread_mutex_lock(&surface_queue->lock);
599 surface_queue->alloc_cb = alloc_cb;
600 surface_queue->free_cb = free_cb;
601 surface_queue->alloc_cb_data = data;
603 pthread_mutex_unlock(&surface_queue->lock);
605 return TBM_SURFACE_QUEUE_ERROR_NONE;
609 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
611 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
613 return surface_queue->width;
617 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
619 return surface_queue->height;
623 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
625 return surface_queue->format;
628 tbm_surface_queue_error_e
629 tbm_surface_queue_set_reset_cb(
630 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
633 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
634 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
636 pthread_mutex_lock(&surface_queue->lock);
638 surface_queue->reset_cb = reset_cb;
639 surface_queue->reset_cb_data = 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_add_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 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
658 pthread_mutex_unlock(&surface_queue->lock);
660 return TBM_SURFACE_QUEUE_ERROR_NONE;
663 tbm_surface_queue_error_e
664 tbm_surface_queue_remove_reset_cb(
665 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
668 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
669 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
671 pthread_mutex_lock(&surface_queue->lock);
673 _notify_remove(&surface_queue->acquirable_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);
692 pthread_mutex_lock(&surface_queue->lock);
694 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
695 if (node == NULL || queue_type != NODE_LIST) {
696 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
698 pthread_mutex_unlock(&surface_queue->lock);
699 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
702 if (surface_queue->impl && surface_queue->impl->enqueue)
703 surface_queue->impl->enqueue(surface_queue, node);
705 _tbm_surface_queue_enqueue(surface_queue, node, 1);
707 if (_queue_is_empty(&surface_queue->dirty_queue)) {
708 pthread_mutex_unlock(&surface_queue->lock);
709 return TBM_SURFACE_QUEUE_ERROR_NONE;
712 pthread_mutex_unlock(&surface_queue->lock);
713 pthread_cond_signal(&surface_queue->dirty_cond);
715 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
716 if (surface_queue->acquirable_cb)
717 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
719 return TBM_SURFACE_QUEUE_ERROR_NONE;
722 tbm_surface_queue_error_e
723 tbm_surface_queue_dequeue(tbm_surface_queue_h
724 surface_queue, tbm_surface_h *surface)
726 queue_node *node = NULL;
728 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
729 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
730 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
731 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
733 pthread_mutex_lock(&surface_queue->lock);
735 if (surface_queue->impl && surface_queue->impl->dequeue)
736 node = surface_queue->impl->dequeue(surface_queue);
738 node = _tbm_surface_queue_dequeue(surface_queue);
742 pthread_mutex_unlock(&surface_queue->lock);
743 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
746 if (node->surface == NULL) {
748 TBM_LOG("_queue_node_pop_front failed\n");
749 pthread_mutex_unlock(&surface_queue->lock);
750 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
753 *surface = node->surface;
755 pthread_mutex_unlock(&surface_queue->lock);
757 return TBM_SURFACE_QUEUE_ERROR_NONE;
761 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
763 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
765 pthread_mutex_lock(&surface_queue->lock);
767 if (_queue_is_empty(&surface_queue->free_queue)) {
768 if (surface_queue->impl && surface_queue->impl->need_attach)
769 surface_queue->impl->need_attach(surface_queue);
772 if (_queue_is_empty(&surface_queue->free_queue)) {
774 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
775 pthread_mutex_unlock(&surface_queue->lock);
779 pthread_mutex_unlock(&surface_queue->lock);
783 pthread_mutex_unlock(&surface_queue->lock);
788 tbm_surface_queue_error_e
789 tbm_surface_queue_release(tbm_surface_queue_h
790 surface_queue, tbm_surface_h surface)
792 queue_node *node = NULL;
795 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
796 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
797 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
798 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
800 pthread_mutex_lock(&surface_queue->lock);
802 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
803 if (node == NULL || queue_type != NODE_LIST) {
804 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
806 pthread_mutex_unlock(&surface_queue->lock);
807 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
810 if (surface_queue->impl && surface_queue->impl->release)
811 surface_queue->impl->release(surface_queue, node);
813 _tbm_surface_queue_release(surface_queue, node, 1);
815 if (_queue_is_empty(&surface_queue->free_queue)) {
816 pthread_mutex_unlock(&surface_queue->lock);
817 return TBM_SURFACE_QUEUE_ERROR_NONE;
820 pthread_mutex_unlock(&surface_queue->lock);
821 pthread_cond_signal(&surface_queue->free_cond);
823 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
824 if (surface_queue->dequeuable_cb)
825 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
827 return TBM_SURFACE_QUEUE_ERROR_NONE;
830 tbm_surface_queue_error_e
831 tbm_surface_queue_acquire(tbm_surface_queue_h
832 surface_queue, tbm_surface_h *surface)
834 queue_node *node = NULL;
836 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
837 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
838 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
839 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
841 pthread_mutex_lock(&surface_queue->lock);
843 if (surface_queue->impl && surface_queue->impl->acquire)
844 node = surface_queue->impl->acquire(surface_queue);
846 node = _tbm_surface_queue_acquire(surface_queue);
850 pthread_mutex_unlock(&surface_queue->lock);
851 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
854 if (node->surface == NULL) {
856 TBM_LOG("_queue_node_pop_front failed\n");
857 pthread_mutex_unlock(&surface_queue->lock);
858 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
861 *surface = node->surface;
863 pthread_mutex_unlock(&surface_queue->lock);
865 return TBM_SURFACE_QUEUE_ERROR_NONE;
869 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
871 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
873 pthread_mutex_lock(&surface_queue->lock);
875 if (_queue_is_empty(&surface_queue->dirty_queue)) {
877 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
878 pthread_mutex_unlock(&surface_queue->lock);
882 pthread_mutex_unlock(&surface_queue->lock);
886 pthread_mutex_unlock(&surface_queue->lock);
892 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
894 queue_node *node = NULL, *tmp = NULL;
896 TBM_RETURN_IF_FAIL(surface_queue != NULL);
898 if (surface_queue->destroy_cb)
899 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
901 _notify_emit(surface_queue, &surface_queue->destory_noti);
903 if (surface_queue->impl && surface_queue->impl->destroy)
904 surface_queue->impl->destroy(surface_queue);
906 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
907 _queue_delete_node(surface_queue, node);
910 _notify_remove_all(&surface_queue->destory_noti);
911 _notify_remove_all(&surface_queue->acquirable_noti);
912 _notify_remove_all(&surface_queue->dequeuable_noti);
913 _notify_remove_all(&surface_queue->reset_noti);
915 pthread_mutex_destroy(&surface_queue->lock);
919 tbm_surface_queue_error_e
920 tbm_surface_queue_reset(tbm_surface_queue_h
921 surface_queue, int width, int height, int format)
923 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
924 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
926 queue_node *node = NULL, *tmp = NULL;
928 if (width == surface_queue->width && height == surface_queue->height &&
929 format == surface_queue->format)
930 return TBM_SURFACE_QUEUE_ERROR_NONE;
932 pthread_mutex_lock(&surface_queue->lock);
934 surface_queue->width = width;
935 surface_queue->height = height;
936 surface_queue->format = format;
938 /* Destory surface and Push to free_queue */
939 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
940 _queue_delete_node(surface_queue, node);
944 _queue_init(&surface_queue->free_queue);
945 _queue_init(&surface_queue->dirty_queue);
946 LIST_INITHEAD(&surface_queue->list);
948 if (surface_queue->impl && surface_queue->impl->reset)
949 surface_queue->impl->reset(surface_queue);
951 pthread_mutex_unlock(&surface_queue->lock);
952 pthread_cond_signal(&surface_queue->free_cond);
954 _notify_emit(surface_queue, &surface_queue->reset_noti);
955 if (surface_queue->reset_cb)
956 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
958 return TBM_SURFACE_QUEUE_ERROR_NONE;
961 tbm_surface_queue_error_e
962 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
964 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
965 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
967 queue_node *node = NULL, *tmp = NULL;
969 pthread_mutex_lock(&surface_queue->lock);
971 /* Destory surface and Push to free_queue */
972 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
973 _queue_delete_node(surface_queue, node);
977 _queue_init(&surface_queue->free_queue);
978 _queue_init(&surface_queue->dirty_queue);
979 LIST_INITHEAD(&surface_queue->list);
981 if (surface_queue->impl && surface_queue->impl->reset)
982 surface_queue->impl->reset(surface_queue);
984 _notify_emit(surface_queue, &surface_queue->reset_noti);
985 if (surface_queue->reset_cb)
986 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
988 pthread_mutex_unlock(&surface_queue->lock);
989 pthread_cond_signal(&surface_queue->free_cond);
991 return TBM_SURFACE_QUEUE_ERROR_NONE;
1001 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1003 tbm_queue_default *data = surface_queue->impl_data;
1005 data->num_attached = 0;
1009 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1011 tbm_queue_default *data = surface_queue->impl_data;
1013 data->num_attached = 0;
1017 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1019 free(surface_queue->impl_data);
1023 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1025 tbm_queue_default *data = surface_queue->impl_data;
1026 tbm_surface_h surface;
1028 if (data->queue_size == data->num_attached)
1031 if (surface_queue->alloc_cb) {
1032 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1033 TBM_RETURN_IF_FAIL(surface != NULL);
1034 tbm_surface_internal_ref(surface);
1036 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1037 surface_queue->height,
1038 surface_queue->format,
1040 TBM_RETURN_IF_FAIL(surface != NULL);
1043 _tbm_surface_queue_attach(surface_queue, surface);
1044 tbm_surface_internal_unref(surface);
1045 data->num_attached++;
1048 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1049 __tbm_queue_default_init,
1050 __tbm_queue_default_reset,
1051 __tbm_queue_default_destroy,
1052 __tbm_queue_default_need_attach,
1053 NULL, /*__tbm_queue_default_enqueue*/
1054 NULL, /*__tbm_queue_default_release*/
1055 NULL, /*__tbm_queue_default_dequeue*/
1056 NULL, /*__tbm_queue_default_acquire*/
1060 tbm_surface_queue_create(int queue_size, int width,
1061 int height, int format, int flags)
1063 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1064 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1065 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1066 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1068 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1069 sizeof(struct _tbm_surface_queue));
1070 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1072 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1073 sizeof(tbm_queue_default));
1075 free(surface_queue);
1079 data->queue_size = queue_size;
1080 data->flags = flags;
1081 _tbm_surface_queue_init(surface_queue,
1082 width, height, format,
1083 &tbm_queue_default_impl, data);
1085 return surface_queue;
1093 } tbm_queue_sequence;
1096 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1098 tbm_queue_sequence *data = surface_queue->impl_data;
1100 data->num_attached = 0;
1101 _queue_init(&data->dequeue_list);
1105 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1107 tbm_queue_sequence *data = surface_queue->impl_data;
1109 data->num_attached = 0;
1110 _queue_init(&data->dequeue_list);
1114 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1116 free(surface_queue->impl_data);
1120 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1122 tbm_queue_sequence *data = surface_queue->impl_data;
1123 tbm_surface_h surface;
1125 if (data->queue_size == data->num_attached)
1128 if (surface_queue->alloc_cb) {
1129 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1130 TBM_RETURN_IF_FAIL(surface != NULL);
1131 tbm_surface_internal_ref(surface);
1133 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1134 surface_queue->height,
1135 surface_queue->format,
1137 TBM_RETURN_IF_FAIL(surface != NULL);
1140 _tbm_surface_queue_attach(surface_queue, surface);
1141 tbm_surface_internal_unref(surface);
1142 data->num_attached++;
1146 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1149 tbm_queue_sequence *data = surface_queue->impl_data;
1150 queue_node *next = NULL;
1151 queue_node *tmp = NULL;
1153 node->priv_flags = 0;
1155 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1156 if (next->priv_flags)
1158 _queue_node_pop(&data->dequeue_list, next);
1159 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1164 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1167 tbm_queue_sequence *data = surface_queue->impl_data;
1168 queue_node *node = NULL;
1170 node = _tbm_surface_queue_dequeue(surface_queue);
1172 _queue_node_push_back(&data->dequeue_list, node);
1173 node->priv_flags = 1;
1179 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1180 __tbm_queue_sequence_init,
1181 __tbm_queue_sequence_reset,
1182 __tbm_queue_sequence_destroy,
1183 __tbm_queue_sequence_need_attach,
1184 __tbm_queue_sequence_enqueue,
1185 NULL, /*__tbm_queue_sequence_release*/
1186 __tbm_queue_sequence_dequeue,
1187 NULL, /*__tbm_queue_sequence_acquire*/
1191 tbm_surface_queue_sequence_create(int queue_size, int width,
1192 int height, int format, int flags)
1194 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1195 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1196 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1197 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1199 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1200 sizeof(struct _tbm_surface_queue));
1201 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1203 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1204 sizeof(tbm_queue_sequence));
1206 free(surface_queue);
1210 data->queue_size = queue_size;
1211 data->flags = flags;
1212 _tbm_surface_queue_init(surface_queue,
1213 width, height, format,
1214 &tbm_queue_sequence_impl, data);
1216 return surface_queue;