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_QUEUE_TRACE(fmt, ...) fprintf(stderr, "[TBM(%d):%s] " fmt, getpid(), __func__, ##__VA_ARGS__)
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)
46 #define TBM_QUEUE_TRACE(fmt, ...)
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 {
94 struct list_head list;
96 struct list_head destory_noti;
97 struct list_head dequeuable_noti;
98 struct list_head acquirable_noti;
99 struct list_head reset_noti;
101 pthread_mutex_t lock;
102 pthread_cond_t free_cond;
103 pthread_cond_t dirty_cond;
105 const tbm_surface_queue_interface *impl;
108 //For external buffer allocation
109 tbm_surface_alloc_cb alloc_cb;
110 tbm_surface_free_cb free_cb;
115 _queue_node_create(void)
117 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
119 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
125 _queue_node_delete(queue_node *node)
127 LIST_DEL(&node->item_link);
128 LIST_DEL(&node->link);
133 _queue_is_empty(queue *queue)
135 if (queue->head.next == &queue->tail)
142 _queue_node_push_back(queue *queue, queue_node *node)
144 LIST_ADDTAIL(&node->item_link, &queue->tail);
149 _queue_node_push_front(queue *queue, queue_node *node)
151 LIST_ADD(&node->item_link, &queue->head);
156 _queue_node_pop_front(queue *queue)
158 queue_node *node = NULL;
160 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
162 LIST_DEL(&node->item_link);
169 _queue_node_pop(queue *queue, queue_node *node)
171 LIST_DEL(&node->item_link);
178 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
179 tbm_surface_h surface, int *out_type)
181 queue_node *node = NULL;
182 queue_node *tmp = NULL;
185 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
189 if (type & FREE_QUEUE) {
190 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
192 if (node->surface == surface) {
194 *out_type = FREE_QUEUE;
201 if (type & DIRTY_QUEUE) {
202 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
204 if (node->surface == surface) {
206 *out_type = DIRTY_QUEUE;
213 if (type & NODE_LIST) {
214 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
215 if (node->surface == surface) {
217 *out_type = NODE_LIST;
228 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
231 if (surface_queue->free_cb) {
232 surface_queue->free_cb(surface_queue,
233 surface_queue->alloc_cb_data,
237 tbm_surface_destroy(node->surface);
240 _queue_node_delete(node);
244 _queue_init(queue *queue)
246 LIST_INITHEAD(&queue->head);
247 LIST_INITHEAD(&queue->tail);
248 LIST_ADDTAIL(&queue->head, &queue->tail);
253 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
256 TBM_RETURN_IF_FAIL(cb != NULL);
258 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
260 TBM_RETURN_IF_FAIL(item != NULL);
262 LIST_INITHEAD(&item->link);
266 LIST_ADDTAIL(&item->link, list);
270 _notify_remove(struct list_head *list,
271 tbm_surface_queue_notify_cb cb, void *data)
273 queue_notify *item = NULL, *tmp = NULL;
275 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
276 if (item->cb == cb && item->data == data) {
277 LIST_DEL(&item->link);
283 TBM_LOG("Cannot find notifiy\n");
287 _notify_remove_all(struct list_head *list)
289 queue_notify *item = NULL, *tmp = NULL;
291 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
292 LIST_DEL(&item->link);
298 _notify_emit(tbm_surface_queue_h surface_queue,
299 struct list_head *list)
301 queue_notify *item = NULL, *tmp = NULL;
303 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
304 item->cb(surface_queue, item->data);
309 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
310 tbm_surface_h surface)
312 queue_node *node = NULL;
314 node = _queue_node_create();
315 TBM_RETURN_IF_FAIL(node != NULL);
317 tbm_surface_internal_ref(surface);
318 node->surface = surface;
320 LIST_ADDTAIL(&node->link, &surface_queue->list);
321 _queue_node_push_back(&surface_queue->free_queue, node);
325 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
326 tbm_surface_h surface)
328 queue_node *node = NULL;
331 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
333 _queue_delete_node(surface_queue, node);
337 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
338 queue_node *node, int push_back)
341 _queue_node_push_back(&surface_queue->dirty_queue, node);
343 _queue_node_push_front(&surface_queue->dirty_queue, node);
347 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
349 queue_node *node = NULL;
351 if (_queue_is_empty(&surface_queue->free_queue)) {
352 if (surface_queue->impl && surface_queue->impl->need_attach)
353 surface_queue->impl->need_attach(surface_queue);
355 if (_queue_is_empty(&surface_queue->free_queue))
359 node = _queue_node_pop_front(&surface_queue->free_queue);
365 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
367 queue_node *node = NULL;
369 if (_queue_is_empty(&surface_queue->dirty_queue))
372 node = _queue_node_pop_front(&surface_queue->dirty_queue);
378 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
379 queue_node *node, int push_back)
382 _queue_node_push_back(&surface_queue->free_queue, node);
384 _queue_node_push_front(&surface_queue->free_queue, node);
388 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
390 int width, int height, int format,
391 const tbm_surface_queue_interface *impl, void *data)
393 TBM_RETURN_IF_FAIL(surface_queue != NULL);
394 TBM_RETURN_IF_FAIL(impl != NULL);
396 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
398 pthread_mutex_init(&surface_queue->lock, NULL);
399 pthread_cond_init(&surface_queue->free_cond, NULL);
400 pthread_cond_init(&surface_queue->dirty_cond, NULL);
402 surface_queue->queue_size = queue_size;
403 surface_queue->width = width;
404 surface_queue->height = height;
405 surface_queue->format = format;
406 surface_queue->impl = impl;
407 surface_queue->impl_data = data;
409 _queue_init(&surface_queue->free_queue);
410 _queue_init(&surface_queue->dirty_queue);
411 LIST_INITHEAD(&surface_queue->list);
413 LIST_INITHEAD(&surface_queue->destory_noti);
414 LIST_INITHEAD(&surface_queue->acquirable_noti);
415 LIST_INITHEAD(&surface_queue->dequeuable_noti);
416 LIST_INITHEAD(&surface_queue->reset_noti);
418 if (surface_queue->impl && surface_queue->impl->init)
419 surface_queue->impl->init(surface_queue);
422 tbm_surface_queue_error_e
423 tbm_surface_queue_add_destroy_cb(
424 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
427 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
428 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
430 pthread_mutex_lock(&surface_queue->lock);
432 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
434 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
436 pthread_mutex_unlock(&surface_queue->lock);
438 return TBM_SURFACE_QUEUE_ERROR_NONE;
441 tbm_surface_queue_error_e
442 tbm_surface_queue_remove_destroy_cb(
443 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
446 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
447 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
449 pthread_mutex_lock(&surface_queue->lock);
451 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
453 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
455 pthread_mutex_unlock(&surface_queue->lock);
457 return TBM_SURFACE_QUEUE_ERROR_NONE;
460 tbm_surface_queue_error_e
461 tbm_surface_queue_add_dequeuable_cb(
462 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
465 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
466 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
468 pthread_mutex_lock(&surface_queue->lock);
470 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
472 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
474 pthread_mutex_unlock(&surface_queue->lock);
476 return TBM_SURFACE_QUEUE_ERROR_NONE;
479 tbm_surface_queue_error_e
480 tbm_surface_queue_remove_dequeuable_cb(
481 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
484 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
485 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
487 pthread_mutex_lock(&surface_queue->lock);
489 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
491 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
493 pthread_mutex_unlock(&surface_queue->lock);
495 return TBM_SURFACE_QUEUE_ERROR_NONE;
498 tbm_surface_queue_error_e
499 tbm_surface_queue_add_acquirable_cb(
500 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
503 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
504 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
506 pthread_mutex_lock(&surface_queue->lock);
508 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
510 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
512 pthread_mutex_unlock(&surface_queue->lock);
514 return TBM_SURFACE_QUEUE_ERROR_NONE;
517 tbm_surface_queue_error_e
518 tbm_surface_queue_remove_acquirable_cb(
519 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
522 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
523 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
525 pthread_mutex_lock(&surface_queue->lock);
527 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
529 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
531 pthread_mutex_unlock(&surface_queue->lock);
533 return TBM_SURFACE_QUEUE_ERROR_NONE;
536 tbm_surface_queue_error_e
537 tbm_surface_queue_set_alloc_cb(
538 tbm_surface_queue_h surface_queue,
539 tbm_surface_alloc_cb alloc_cb,
540 tbm_surface_free_cb free_cb,
543 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
544 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
546 pthread_mutex_lock(&surface_queue->lock);
548 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
550 surface_queue->alloc_cb = alloc_cb;
551 surface_queue->free_cb = free_cb;
552 surface_queue->alloc_cb_data = data;
554 pthread_mutex_unlock(&surface_queue->lock);
556 return TBM_SURFACE_QUEUE_ERROR_NONE;
560 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
562 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
564 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
566 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
568 return surface_queue->width;
572 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
574 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
576 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
578 return surface_queue->height;
582 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
584 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
586 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
588 return surface_queue->format;
592 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
594 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
596 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
598 return surface_queue->queue_size;
601 tbm_surface_queue_error_e
602 tbm_surface_queue_add_reset_cb(
603 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
606 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
607 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
609 pthread_mutex_lock(&surface_queue->lock);
611 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
613 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
615 pthread_mutex_unlock(&surface_queue->lock);
617 return TBM_SURFACE_QUEUE_ERROR_NONE;
620 tbm_surface_queue_error_e
621 tbm_surface_queue_remove_reset_cb(
622 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
625 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
626 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
628 pthread_mutex_lock(&surface_queue->lock);
630 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
632 _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
634 pthread_mutex_unlock(&surface_queue->lock);
636 return TBM_SURFACE_QUEUE_ERROR_NONE;
639 tbm_surface_queue_error_e
640 tbm_surface_queue_enqueue(tbm_surface_queue_h
641 surface_queue, tbm_surface_h surface)
643 queue_node *node = NULL;
646 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
647 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
648 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
649 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
651 pthread_mutex_lock(&surface_queue->lock);
653 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
655 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
656 if (node == NULL || queue_type != NODE_LIST) {
657 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
659 pthread_mutex_unlock(&surface_queue->lock);
660 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
663 if (surface_queue->impl && surface_queue->impl->enqueue)
664 surface_queue->impl->enqueue(surface_queue, node);
666 _tbm_surface_queue_enqueue(surface_queue, node, 1);
668 if (_queue_is_empty(&surface_queue->dirty_queue)) {
669 pthread_mutex_unlock(&surface_queue->lock);
670 return TBM_SURFACE_QUEUE_ERROR_NONE;
673 pthread_mutex_unlock(&surface_queue->lock);
674 pthread_cond_signal(&surface_queue->dirty_cond);
676 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
678 return TBM_SURFACE_QUEUE_ERROR_NONE;
681 tbm_surface_queue_error_e
682 tbm_surface_queue_dequeue(tbm_surface_queue_h
683 surface_queue, tbm_surface_h *surface)
685 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 if (surface_queue->impl && surface_queue->impl->dequeue)
695 node = surface_queue->impl->dequeue(surface_queue);
697 node = _tbm_surface_queue_dequeue(surface_queue);
701 pthread_mutex_unlock(&surface_queue->lock);
702 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
705 if (node->surface == NULL) {
707 TBM_LOG("_queue_node_pop_front failed\n");
708 pthread_mutex_unlock(&surface_queue->lock);
709 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
712 *surface = node->surface;
714 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
716 pthread_mutex_unlock(&surface_queue->lock);
718 return TBM_SURFACE_QUEUE_ERROR_NONE;
722 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
724 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
726 pthread_mutex_lock(&surface_queue->lock);
728 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
730 if (_queue_is_empty(&surface_queue->free_queue)) {
731 if (surface_queue->impl && surface_queue->impl->need_attach)
732 surface_queue->impl->need_attach(surface_queue);
735 if (_queue_is_empty(&surface_queue->free_queue)) {
737 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
738 pthread_mutex_unlock(&surface_queue->lock);
742 pthread_mutex_unlock(&surface_queue->lock);
746 pthread_mutex_unlock(&surface_queue->lock);
751 tbm_surface_queue_error_e
752 tbm_surface_queue_release(tbm_surface_queue_h
753 surface_queue, tbm_surface_h surface)
755 queue_node *node = NULL;
758 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
759 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
760 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
761 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
763 pthread_mutex_lock(&surface_queue->lock);
765 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
767 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
768 if (node == NULL || queue_type != NODE_LIST) {
769 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
771 pthread_mutex_unlock(&surface_queue->lock);
772 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
775 if (surface_queue->impl && surface_queue->impl->release)
776 surface_queue->impl->release(surface_queue, node);
778 _tbm_surface_queue_release(surface_queue, node, 1);
780 if (_queue_is_empty(&surface_queue->free_queue)) {
781 pthread_mutex_unlock(&surface_queue->lock);
782 return TBM_SURFACE_QUEUE_ERROR_NONE;
785 pthread_mutex_unlock(&surface_queue->lock);
786 pthread_cond_signal(&surface_queue->free_cond);
788 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
790 return TBM_SURFACE_QUEUE_ERROR_NONE;
793 tbm_surface_queue_error_e
794 tbm_surface_queue_acquire(tbm_surface_queue_h
795 surface_queue, tbm_surface_h *surface)
797 queue_node *node = NULL;
799 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
800 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
801 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
802 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
804 pthread_mutex_lock(&surface_queue->lock);
806 if (surface_queue->impl && surface_queue->impl->acquire)
807 node = surface_queue->impl->acquire(surface_queue);
809 node = _tbm_surface_queue_acquire(surface_queue);
813 pthread_mutex_unlock(&surface_queue->lock);
814 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
817 if (node->surface == NULL) {
819 TBM_LOG("_queue_node_pop_front failed\n");
820 pthread_mutex_unlock(&surface_queue->lock);
821 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
824 *surface = node->surface;
826 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
828 pthread_mutex_unlock(&surface_queue->lock);
830 return TBM_SURFACE_QUEUE_ERROR_NONE;
834 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
836 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
838 pthread_mutex_lock(&surface_queue->lock);
840 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
842 if (_queue_is_empty(&surface_queue->dirty_queue)) {
844 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
845 pthread_mutex_unlock(&surface_queue->lock);
849 pthread_mutex_unlock(&surface_queue->lock);
853 pthread_mutex_unlock(&surface_queue->lock);
859 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
861 queue_node *node = NULL, *tmp = NULL;
863 TBM_RETURN_IF_FAIL(surface_queue != NULL);
865 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
867 _notify_emit(surface_queue, &surface_queue->destory_noti);
869 if (surface_queue->impl && surface_queue->impl->destroy)
870 surface_queue->impl->destroy(surface_queue);
872 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
873 _queue_delete_node(surface_queue, node);
876 _notify_remove_all(&surface_queue->destory_noti);
877 _notify_remove_all(&surface_queue->acquirable_noti);
878 _notify_remove_all(&surface_queue->dequeuable_noti);
879 _notify_remove_all(&surface_queue->reset_noti);
881 pthread_mutex_destroy(&surface_queue->lock);
885 tbm_surface_queue_error_e
886 tbm_surface_queue_reset(tbm_surface_queue_h
887 surface_queue, int width, int height, int format)
889 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
890 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
892 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
894 queue_node *node = NULL, *tmp = NULL;
896 if (width == surface_queue->width && height == surface_queue->height &&
897 format == surface_queue->format)
898 return TBM_SURFACE_QUEUE_ERROR_NONE;
900 pthread_mutex_lock(&surface_queue->lock);
902 surface_queue->width = width;
903 surface_queue->height = height;
904 surface_queue->format = format;
906 /* Destory surface and Push to free_queue */
907 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
908 _queue_delete_node(surface_queue, node);
912 _queue_init(&surface_queue->free_queue);
913 _queue_init(&surface_queue->dirty_queue);
914 LIST_INITHEAD(&surface_queue->list);
916 if (surface_queue->impl && surface_queue->impl->reset)
917 surface_queue->impl->reset(surface_queue);
919 pthread_mutex_unlock(&surface_queue->lock);
920 pthread_cond_signal(&surface_queue->free_cond);
922 _notify_emit(surface_queue, &surface_queue->reset_noti);
924 return TBM_SURFACE_QUEUE_ERROR_NONE;
927 tbm_surface_queue_error_e
928 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
930 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
931 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
933 queue_node *node = NULL, *tmp = NULL;
935 pthread_mutex_lock(&surface_queue->lock);
937 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
939 /* Destory surface and Push to free_queue */
940 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
941 _queue_delete_node(surface_queue, node);
945 _queue_init(&surface_queue->free_queue);
946 _queue_init(&surface_queue->dirty_queue);
947 LIST_INITHEAD(&surface_queue->list);
949 if (surface_queue->impl && surface_queue->impl->reset)
950 surface_queue->impl->reset(surface_queue);
952 _notify_emit(surface_queue, &surface_queue->reset_noti);
954 pthread_mutex_unlock(&surface_queue->lock);
955 pthread_cond_signal(&surface_queue->free_cond);
957 return TBM_SURFACE_QUEUE_ERROR_NONE;
967 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
969 tbm_queue_default *data = surface_queue->impl_data;
971 data->num_attached = 0;
975 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
977 tbm_queue_default *data = surface_queue->impl_data;
979 data->num_attached = 0;
983 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
985 free(surface_queue->impl_data);
989 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
991 tbm_queue_default *data = surface_queue->impl_data;
992 tbm_surface_h surface;
994 if (data->queue_size == data->num_attached)
997 if (surface_queue->alloc_cb) {
998 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
999 TBM_RETURN_IF_FAIL(surface != NULL);
1000 tbm_surface_internal_ref(surface);
1002 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1003 surface_queue->height,
1004 surface_queue->format,
1006 TBM_RETURN_IF_FAIL(surface != NULL);
1009 _tbm_surface_queue_attach(surface_queue, surface);
1010 tbm_surface_internal_unref(surface);
1011 data->num_attached++;
1014 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1015 __tbm_queue_default_init,
1016 __tbm_queue_default_reset,
1017 __tbm_queue_default_destroy,
1018 __tbm_queue_default_need_attach,
1019 NULL, /*__tbm_queue_default_enqueue*/
1020 NULL, /*__tbm_queue_default_release*/
1021 NULL, /*__tbm_queue_default_dequeue*/
1022 NULL, /*__tbm_queue_default_acquire*/
1026 tbm_surface_queue_create(int queue_size, int width,
1027 int height, int format, int flags)
1029 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1030 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1031 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1032 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1034 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1035 sizeof(struct _tbm_surface_queue));
1036 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1038 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1040 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1041 sizeof(tbm_queue_default));
1043 free(surface_queue);
1047 data->queue_size = queue_size;
1048 data->flags = flags;
1049 _tbm_surface_queue_init(surface_queue,
1051 width, height, format,
1052 &tbm_queue_default_impl, data);
1054 return surface_queue;
1062 } tbm_queue_sequence;
1065 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1067 tbm_queue_sequence *data = surface_queue->impl_data;
1069 data->num_attached = 0;
1070 _queue_init(&data->dequeue_list);
1074 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1076 tbm_queue_sequence *data = surface_queue->impl_data;
1078 data->num_attached = 0;
1079 _queue_init(&data->dequeue_list);
1083 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1085 free(surface_queue->impl_data);
1089 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1091 tbm_queue_sequence *data = surface_queue->impl_data;
1092 tbm_surface_h surface;
1094 if (data->queue_size == data->num_attached)
1097 if (surface_queue->alloc_cb) {
1098 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1099 TBM_RETURN_IF_FAIL(surface != NULL);
1100 tbm_surface_internal_ref(surface);
1102 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1103 surface_queue->height,
1104 surface_queue->format,
1106 TBM_RETURN_IF_FAIL(surface != NULL);
1109 _tbm_surface_queue_attach(surface_queue, surface);
1110 tbm_surface_internal_unref(surface);
1111 data->num_attached++;
1115 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1118 tbm_queue_sequence *data = surface_queue->impl_data;
1119 queue_node *next = NULL;
1120 queue_node *tmp = NULL;
1122 node->priv_flags = 0;
1124 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1125 if (next->priv_flags)
1127 _queue_node_pop(&data->dequeue_list, next);
1128 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1133 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1136 tbm_queue_sequence *data = surface_queue->impl_data;
1137 queue_node *node = NULL;
1139 node = _tbm_surface_queue_dequeue(surface_queue);
1141 _queue_node_push_back(&data->dequeue_list, node);
1142 node->priv_flags = 1;
1148 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1149 __tbm_queue_sequence_init,
1150 __tbm_queue_sequence_reset,
1151 __tbm_queue_sequence_destroy,
1152 __tbm_queue_sequence_need_attach,
1153 __tbm_queue_sequence_enqueue,
1154 NULL, /*__tbm_queue_sequence_release*/
1155 __tbm_queue_sequence_dequeue,
1156 NULL, /*__tbm_queue_sequence_acquire*/
1160 tbm_surface_queue_sequence_create(int queue_size, int width,
1161 int height, int format, int flags)
1163 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1164 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1165 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1166 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1168 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1169 sizeof(struct _tbm_surface_queue));
1170 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1172 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1174 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1175 sizeof(tbm_queue_sequence));
1177 free(surface_queue);
1181 data->queue_size = queue_size;
1182 data->flags = flags;
1183 _tbm_surface_queue_init(surface_queue,
1185 width, height, format,
1186 &tbm_queue_sequence_impl, data);
1188 return surface_queue;