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)
56 struct list_head head;
61 tbm_surface_h surface;
63 struct list_head item_link;
64 struct list_head link;
66 unsigned int priv_flags; /*for each queue*/
70 struct list_head link;
72 tbm_surface_queue_notify_cb cb;
76 typedef struct _tbm_surface_queue_interface {
77 void (*init)(tbm_surface_queue_h queue);
78 void (*reset)(tbm_surface_queue_h queue);
79 void (*destroy)(tbm_surface_queue_h queue);
80 void (*need_attach)(tbm_surface_queue_h queue);
82 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
83 void (*release)(tbm_surface_queue_h queue, queue_node *node);
84 queue_node *(*dequeue)(tbm_surface_queue_h queue);
85 queue_node *(*acquire)(tbm_surface_queue_h queue);
86 } tbm_surface_queue_interface;
88 struct _tbm_surface_queue {
96 struct list_head list;
98 struct list_head destory_noti;
99 struct list_head dequeuable_noti;
100 struct list_head acquirable_noti;
101 struct list_head reset_noti;
103 pthread_mutex_t lock;
104 pthread_cond_t free_cond;
105 pthread_cond_t dirty_cond;
107 const tbm_surface_queue_interface *impl;
110 //For external buffer allocation
111 tbm_surface_alloc_cb alloc_cb;
112 tbm_surface_free_cb free_cb;
116 /* LCOV_EXCL_START */
118 _queue_node_create(void)
120 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
122 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
128 _queue_node_delete(queue_node *node)
130 LIST_DEL(&node->item_link);
131 LIST_DEL(&node->link);
136 _queue_is_empty(queue *queue)
138 if (LIST_IS_EMPTY(&queue->head))
145 _queue_node_push_back(queue *queue, queue_node *node)
147 LIST_ADDTAIL(&node->item_link, &queue->head);
152 _queue_node_push_front(queue *queue, queue_node *node)
154 LIST_ADD(&node->item_link, &queue->head);
159 _queue_node_pop_front(queue *queue)
161 queue_node *node = NULL;
163 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
165 LIST_DEL(&node->item_link);
172 _queue_node_pop(queue *queue, queue_node *node)
174 LIST_DEL(&node->item_link);
181 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
182 tbm_surface_h surface, int *out_type)
184 queue_node *node = NULL;
185 queue_node *tmp = NULL;
188 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
192 if (type & FREE_QUEUE) {
193 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
195 if (node->surface == surface) {
197 *out_type = FREE_QUEUE;
204 if (type & DIRTY_QUEUE) {
205 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
207 if (node->surface == surface) {
209 *out_type = DIRTY_QUEUE;
216 if (type & NODE_LIST) {
217 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
218 if (node->surface == surface) {
220 *out_type = NODE_LIST;
231 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
234 if (surface_queue->free_cb) {
235 surface_queue->free_cb(surface_queue,
236 surface_queue->alloc_cb_data,
240 tbm_surface_destroy(node->surface);
243 _queue_node_delete(node);
247 _queue_init(queue *queue)
249 LIST_INITHEAD(&queue->head);
255 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
258 TBM_RETURN_IF_FAIL(cb != NULL);
260 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
262 TBM_RETURN_IF_FAIL(item != NULL);
264 LIST_INITHEAD(&item->link);
268 LIST_ADDTAIL(&item->link, list);
272 _notify_remove(struct list_head *list,
273 tbm_surface_queue_notify_cb cb, void *data)
275 queue_notify *item = NULL, *tmp = NULL;
277 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
278 if (item->cb == cb && item->data == data) {
279 LIST_DEL(&item->link);
285 TBM_LOG_E("Cannot find notifiy\n");
289 _notify_remove_all(struct list_head *list)
291 queue_notify *item = NULL, *tmp = NULL;
293 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
294 LIST_DEL(&item->link);
300 _notify_emit(tbm_surface_queue_h surface_queue,
301 struct list_head *list)
303 queue_notify *item = NULL, *tmp = NULL;
305 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
306 item->cb(surface_queue, item->data);
311 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
312 tbm_surface_h surface)
314 queue_node *node = NULL;
316 node = _queue_node_create();
317 TBM_RETURN_IF_FAIL(node != NULL);
319 tbm_surface_internal_ref(surface);
320 node->surface = surface;
322 LIST_ADDTAIL(&node->link, &surface_queue->list);
323 _queue_node_push_back(&surface_queue->free_queue, node);
327 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
328 tbm_surface_h surface)
330 queue_node *node = NULL;
333 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
335 _queue_delete_node(surface_queue, node);
339 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
340 queue_node *node, int push_back)
343 _queue_node_push_back(&surface_queue->dirty_queue, node);
345 _queue_node_push_front(&surface_queue->dirty_queue, node);
349 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
351 queue_node *node = NULL;
353 if (_queue_is_empty(&surface_queue->free_queue)) {
354 if (surface_queue->impl && surface_queue->impl->need_attach)
355 surface_queue->impl->need_attach(surface_queue);
357 if (_queue_is_empty(&surface_queue->free_queue))
361 node = _queue_node_pop_front(&surface_queue->free_queue);
367 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
369 queue_node *node = NULL;
371 if (_queue_is_empty(&surface_queue->dirty_queue))
374 node = _queue_node_pop_front(&surface_queue->dirty_queue);
380 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
381 queue_node *node, int push_back)
384 _queue_node_push_back(&surface_queue->free_queue, node);
386 _queue_node_push_front(&surface_queue->free_queue, node);
390 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
392 int width, int height, int format,
393 const tbm_surface_queue_interface *impl, void *data)
395 TBM_RETURN_IF_FAIL(surface_queue != NULL);
396 TBM_RETURN_IF_FAIL(impl != NULL);
398 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
400 pthread_mutex_init(&surface_queue->lock, NULL);
401 pthread_cond_init(&surface_queue->free_cond, NULL);
402 pthread_cond_init(&surface_queue->dirty_cond, NULL);
404 surface_queue->queue_size = queue_size;
405 surface_queue->width = width;
406 surface_queue->height = height;
407 surface_queue->format = format;
408 surface_queue->impl = impl;
409 surface_queue->impl_data = data;
411 _queue_init(&surface_queue->free_queue);
412 _queue_init(&surface_queue->dirty_queue);
413 LIST_INITHEAD(&surface_queue->list);
415 LIST_INITHEAD(&surface_queue->destory_noti);
416 LIST_INITHEAD(&surface_queue->acquirable_noti);
417 LIST_INITHEAD(&surface_queue->dequeuable_noti);
418 LIST_INITHEAD(&surface_queue->reset_noti);
420 if (surface_queue->impl && surface_queue->impl->init)
421 surface_queue->impl->init(surface_queue);
424 tbm_surface_queue_error_e
425 tbm_surface_queue_add_destroy_cb(
426 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
429 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
430 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
432 pthread_mutex_lock(&surface_queue->lock);
434 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
436 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
438 pthread_mutex_unlock(&surface_queue->lock);
440 return TBM_SURFACE_QUEUE_ERROR_NONE;
443 tbm_surface_queue_error_e
444 tbm_surface_queue_remove_destroy_cb(
445 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
448 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
449 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
451 pthread_mutex_lock(&surface_queue->lock);
453 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
455 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
457 pthread_mutex_unlock(&surface_queue->lock);
459 return TBM_SURFACE_QUEUE_ERROR_NONE;
462 tbm_surface_queue_error_e
463 tbm_surface_queue_add_dequeuable_cb(
464 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
467 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
468 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
470 pthread_mutex_lock(&surface_queue->lock);
472 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
474 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
476 pthread_mutex_unlock(&surface_queue->lock);
478 return TBM_SURFACE_QUEUE_ERROR_NONE;
481 tbm_surface_queue_error_e
482 tbm_surface_queue_remove_dequeuable_cb(
483 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
486 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
487 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
489 pthread_mutex_lock(&surface_queue->lock);
491 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
493 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
495 pthread_mutex_unlock(&surface_queue->lock);
497 return TBM_SURFACE_QUEUE_ERROR_NONE;
500 tbm_surface_queue_error_e
501 tbm_surface_queue_add_acquirable_cb(
502 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
505 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
506 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
508 pthread_mutex_lock(&surface_queue->lock);
510 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
512 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
514 pthread_mutex_unlock(&surface_queue->lock);
516 return TBM_SURFACE_QUEUE_ERROR_NONE;
519 tbm_surface_queue_error_e
520 tbm_surface_queue_remove_acquirable_cb(
521 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
524 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
525 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
527 pthread_mutex_lock(&surface_queue->lock);
529 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
531 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
533 pthread_mutex_unlock(&surface_queue->lock);
535 return TBM_SURFACE_QUEUE_ERROR_NONE;
538 tbm_surface_queue_error_e
539 tbm_surface_queue_set_alloc_cb(
540 tbm_surface_queue_h surface_queue,
541 tbm_surface_alloc_cb alloc_cb,
542 tbm_surface_free_cb free_cb,
545 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
546 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
548 pthread_mutex_lock(&surface_queue->lock);
550 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
552 surface_queue->alloc_cb = alloc_cb;
553 surface_queue->free_cb = free_cb;
554 surface_queue->alloc_cb_data = data;
556 pthread_mutex_unlock(&surface_queue->lock);
558 return TBM_SURFACE_QUEUE_ERROR_NONE;
562 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
564 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
566 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
568 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
570 return surface_queue->width;
574 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
576 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
578 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
580 return surface_queue->height;
584 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
586 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
588 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
590 return surface_queue->format;
594 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
596 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
598 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
600 return surface_queue->queue_size;
603 tbm_surface_queue_error_e
604 tbm_surface_queue_add_reset_cb(
605 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
608 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
609 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
611 pthread_mutex_lock(&surface_queue->lock);
613 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
615 _notify_add(&surface_queue->reset_noti, reset_cb, data);
617 pthread_mutex_unlock(&surface_queue->lock);
619 return TBM_SURFACE_QUEUE_ERROR_NONE;
622 tbm_surface_queue_error_e
623 tbm_surface_queue_remove_reset_cb(
624 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
627 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
628 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
630 pthread_mutex_lock(&surface_queue->lock);
632 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
634 _notify_remove(&surface_queue->reset_noti, reset_cb, data);
636 pthread_mutex_unlock(&surface_queue->lock);
638 return TBM_SURFACE_QUEUE_ERROR_NONE;
641 tbm_surface_queue_error_e
642 tbm_surface_queue_enqueue(tbm_surface_queue_h
643 surface_queue, tbm_surface_h surface)
645 queue_node *node = NULL;
648 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
649 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
650 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
651 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
653 pthread_mutex_lock(&surface_queue->lock);
655 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
657 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
658 if (node == NULL || queue_type != NODE_LIST) {
659 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
661 pthread_mutex_unlock(&surface_queue->lock);
662 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
665 if (surface_queue->impl && surface_queue->impl->enqueue)
666 surface_queue->impl->enqueue(surface_queue, node);
668 _tbm_surface_queue_enqueue(surface_queue, node, 1);
670 if (_queue_is_empty(&surface_queue->dirty_queue)) {
671 pthread_mutex_unlock(&surface_queue->lock);
672 return TBM_SURFACE_QUEUE_ERROR_NONE;
675 pthread_mutex_unlock(&surface_queue->lock);
676 pthread_cond_signal(&surface_queue->dirty_cond);
678 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
680 return TBM_SURFACE_QUEUE_ERROR_NONE;
683 tbm_surface_queue_error_e
684 tbm_surface_queue_dequeue(tbm_surface_queue_h
685 surface_queue, tbm_surface_h *surface)
687 queue_node *node = NULL;
689 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
690 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
691 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
692 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
694 pthread_mutex_lock(&surface_queue->lock);
696 if (surface_queue->impl && surface_queue->impl->dequeue)
697 node = surface_queue->impl->dequeue(surface_queue);
699 node = _tbm_surface_queue_dequeue(surface_queue);
703 pthread_mutex_unlock(&surface_queue->lock);
704 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
707 if (node->surface == NULL) {
709 TBM_LOG_E("_queue_node_pop_front failed\n");
710 pthread_mutex_unlock(&surface_queue->lock);
711 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
714 *surface = node->surface;
716 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
718 pthread_mutex_unlock(&surface_queue->lock);
720 return TBM_SURFACE_QUEUE_ERROR_NONE;
724 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
726 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
728 pthread_mutex_lock(&surface_queue->lock);
730 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
732 if (_queue_is_empty(&surface_queue->free_queue)) {
733 if (surface_queue->impl && surface_queue->impl->need_attach)
734 surface_queue->impl->need_attach(surface_queue);
737 if (_queue_is_empty(&surface_queue->free_queue)) {
739 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
740 pthread_mutex_unlock(&surface_queue->lock);
744 pthread_mutex_unlock(&surface_queue->lock);
748 pthread_mutex_unlock(&surface_queue->lock);
753 tbm_surface_queue_error_e
754 tbm_surface_queue_release(tbm_surface_queue_h
755 surface_queue, tbm_surface_h surface)
757 queue_node *node = NULL;
760 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
761 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
762 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
763 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
765 pthread_mutex_lock(&surface_queue->lock);
767 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
769 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
770 if (node == NULL || queue_type != NODE_LIST) {
771 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
773 pthread_mutex_unlock(&surface_queue->lock);
774 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
777 if (surface_queue->impl && surface_queue->impl->release)
778 surface_queue->impl->release(surface_queue, node);
780 _tbm_surface_queue_release(surface_queue, node, 1);
782 if (_queue_is_empty(&surface_queue->free_queue)) {
783 pthread_mutex_unlock(&surface_queue->lock);
784 return TBM_SURFACE_QUEUE_ERROR_NONE;
787 pthread_mutex_unlock(&surface_queue->lock);
788 pthread_cond_signal(&surface_queue->free_cond);
790 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
792 return TBM_SURFACE_QUEUE_ERROR_NONE;
795 tbm_surface_queue_error_e
796 tbm_surface_queue_acquire(tbm_surface_queue_h
797 surface_queue, tbm_surface_h *surface)
799 queue_node *node = NULL;
801 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
802 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
803 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
804 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
806 pthread_mutex_lock(&surface_queue->lock);
808 if (surface_queue->impl && surface_queue->impl->acquire)
809 node = surface_queue->impl->acquire(surface_queue);
811 node = _tbm_surface_queue_acquire(surface_queue);
815 pthread_mutex_unlock(&surface_queue->lock);
816 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
819 if (node->surface == NULL) {
821 TBM_LOG_E("_queue_node_pop_front failed\n");
822 pthread_mutex_unlock(&surface_queue->lock);
823 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
826 *surface = node->surface;
828 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
830 pthread_mutex_unlock(&surface_queue->lock);
832 return TBM_SURFACE_QUEUE_ERROR_NONE;
836 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
838 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
840 pthread_mutex_lock(&surface_queue->lock);
842 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
844 if (_queue_is_empty(&surface_queue->dirty_queue)) {
846 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
847 pthread_mutex_unlock(&surface_queue->lock);
851 pthread_mutex_unlock(&surface_queue->lock);
855 pthread_mutex_unlock(&surface_queue->lock);
861 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
863 queue_node *node = NULL, *tmp = NULL;
865 TBM_RETURN_IF_FAIL(surface_queue != NULL);
867 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
869 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
870 _queue_delete_node(surface_queue, node);
873 _notify_emit(surface_queue, &surface_queue->destory_noti);
875 if (surface_queue->impl && surface_queue->impl->destroy)
876 surface_queue->impl->destroy(surface_queue);
878 _notify_remove_all(&surface_queue->destory_noti);
879 _notify_remove_all(&surface_queue->acquirable_noti);
880 _notify_remove_all(&surface_queue->dequeuable_noti);
881 _notify_remove_all(&surface_queue->reset_noti);
883 pthread_mutex_destroy(&surface_queue->lock);
887 tbm_surface_queue_error_e
888 tbm_surface_queue_reset(tbm_surface_queue_h
889 surface_queue, int width, int height, int format)
891 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
892 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
894 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
896 queue_node *node = NULL, *tmp = NULL;
898 if (width == surface_queue->width && height == surface_queue->height &&
899 format == surface_queue->format)
900 return TBM_SURFACE_QUEUE_ERROR_NONE;
902 pthread_mutex_lock(&surface_queue->lock);
904 surface_queue->width = width;
905 surface_queue->height = height;
906 surface_queue->format = format;
908 /* Destory surface and Push to free_queue */
909 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
910 _queue_delete_node(surface_queue, node);
914 _queue_init(&surface_queue->free_queue);
915 _queue_init(&surface_queue->dirty_queue);
916 LIST_INITHEAD(&surface_queue->list);
918 if (surface_queue->impl && surface_queue->impl->reset)
919 surface_queue->impl->reset(surface_queue);
921 pthread_mutex_unlock(&surface_queue->lock);
922 pthread_cond_signal(&surface_queue->free_cond);
924 _notify_emit(surface_queue, &surface_queue->reset_noti);
926 return TBM_SURFACE_QUEUE_ERROR_NONE;
929 tbm_surface_queue_error_e
930 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
932 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
933 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
935 queue_node *node = NULL, *tmp = NULL;
937 pthread_mutex_lock(&surface_queue->lock);
939 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
941 /* Destory surface and Push to free_queue */
942 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
943 _queue_delete_node(surface_queue, node);
947 _queue_init(&surface_queue->free_queue);
948 _queue_init(&surface_queue->dirty_queue);
949 LIST_INITHEAD(&surface_queue->list);
951 if (surface_queue->impl && surface_queue->impl->reset)
952 surface_queue->impl->reset(surface_queue);
954 _notify_emit(surface_queue, &surface_queue->reset_noti);
956 pthread_mutex_unlock(&surface_queue->lock);
957 pthread_cond_signal(&surface_queue->free_cond);
959 return TBM_SURFACE_QUEUE_ERROR_NONE;
962 tbm_surface_queue_error_e
963 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
964 tbm_surface_h *surfaces, int *num)
966 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
967 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
968 TBM_RETURN_VAL_IF_FAIL(num != NULL,
969 TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
971 queue_node *node = NULL;
972 queue_node *tmp = NULL;
974 pthread_mutex_lock(&surface_queue->lock);
977 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
979 surfaces[*num] = node->surface;
984 pthread_mutex_unlock(&surface_queue->lock);
986 return TBM_SURFACE_QUEUE_ERROR_NONE;
996 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
998 tbm_queue_default *data = surface_queue->impl_data;
1000 data->num_attached = 0;
1004 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1006 tbm_queue_default *data = surface_queue->impl_data;
1008 data->num_attached = 0;
1012 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1014 free(surface_queue->impl_data);
1018 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1020 tbm_queue_default *data = surface_queue->impl_data;
1021 tbm_surface_h surface;
1023 if (data->queue_size == data->num_attached)
1026 if (surface_queue->alloc_cb) {
1027 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1028 TBM_RETURN_IF_FAIL(surface != NULL);
1029 tbm_surface_internal_ref(surface);
1031 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1032 surface_queue->height,
1033 surface_queue->format,
1035 TBM_RETURN_IF_FAIL(surface != NULL);
1038 _tbm_surface_queue_attach(surface_queue, surface);
1039 tbm_surface_internal_unref(surface);
1040 data->num_attached++;
1043 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1044 __tbm_queue_default_init,
1045 __tbm_queue_default_reset,
1046 __tbm_queue_default_destroy,
1047 __tbm_queue_default_need_attach,
1048 NULL, /*__tbm_queue_default_enqueue*/
1049 NULL, /*__tbm_queue_default_release*/
1050 NULL, /*__tbm_queue_default_dequeue*/
1051 NULL, /*__tbm_queue_default_acquire*/
1055 tbm_surface_queue_create(int queue_size, int width,
1056 int height, int format, int flags)
1058 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1059 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1060 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1061 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1063 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1064 sizeof(struct _tbm_surface_queue));
1065 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1067 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1069 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1070 sizeof(tbm_queue_default));
1072 free(surface_queue);
1076 data->queue_size = queue_size;
1077 data->flags = flags;
1078 _tbm_surface_queue_init(surface_queue,
1080 width, height, format,
1081 &tbm_queue_default_impl, data);
1083 return surface_queue;
1091 } tbm_queue_sequence;
1094 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1096 tbm_queue_sequence *data = surface_queue->impl_data;
1098 data->num_attached = 0;
1099 _queue_init(&data->dequeue_list);
1103 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1105 tbm_queue_sequence *data = surface_queue->impl_data;
1107 data->num_attached = 0;
1108 _queue_init(&data->dequeue_list);
1112 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1114 free(surface_queue->impl_data);
1118 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1120 tbm_queue_sequence *data = surface_queue->impl_data;
1121 tbm_surface_h surface;
1123 if (data->queue_size == data->num_attached)
1126 if (surface_queue->alloc_cb) {
1127 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1128 TBM_RETURN_IF_FAIL(surface != NULL);
1129 tbm_surface_internal_ref(surface);
1131 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1132 surface_queue->height,
1133 surface_queue->format,
1135 TBM_RETURN_IF_FAIL(surface != NULL);
1138 _tbm_surface_queue_attach(surface_queue, surface);
1139 tbm_surface_internal_unref(surface);
1140 data->num_attached++;
1144 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1147 tbm_queue_sequence *data = surface_queue->impl_data;
1148 queue_node *next = NULL;
1149 queue_node *tmp = NULL;
1151 node->priv_flags = 0;
1153 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1154 if (next->priv_flags)
1156 _queue_node_pop(&data->dequeue_list, next);
1157 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1162 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1165 tbm_queue_sequence *data = surface_queue->impl_data;
1166 queue_node *node = NULL;
1168 node = _tbm_surface_queue_dequeue(surface_queue);
1170 _queue_node_push_back(&data->dequeue_list, node);
1171 node->priv_flags = 1;
1177 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1178 __tbm_queue_sequence_init,
1179 __tbm_queue_sequence_reset,
1180 __tbm_queue_sequence_destroy,
1181 __tbm_queue_sequence_need_attach,
1182 __tbm_queue_sequence_enqueue,
1183 NULL, /*__tbm_queue_sequence_release*/
1184 __tbm_queue_sequence_dequeue,
1185 NULL, /*__tbm_queue_sequence_acquire*/
1189 tbm_surface_queue_sequence_create(int queue_size, int width,
1190 int height, int format, int flags)
1192 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1193 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1194 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1195 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1197 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1198 sizeof(struct _tbm_surface_queue));
1199 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1201 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
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,
1214 width, height, format,
1215 &tbm_queue_sequence_impl, data);
1217 return surface_queue;
1219 /* LCOV_EXCL_STOP */