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;
57 tbm_surface_h surface;
59 struct list_head item_link;
60 struct list_head link;
62 unsigned int priv_flags; /*for each queue*/
66 struct list_head link;
68 tbm_surface_queue_notify_cb cb;
72 typedef struct _tbm_surface_queue_interface {
73 void (*init)(tbm_surface_queue_h queue);
74 void (*reset)(tbm_surface_queue_h queue);
75 void (*destroy)(tbm_surface_queue_h queue);
76 void (*need_attach)(tbm_surface_queue_h queue);
78 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
79 void (*release)(tbm_surface_queue_h queue, queue_node *node);
80 queue_node *(*dequeue)(tbm_surface_queue_h queue);
81 queue_node *(*acquire)(tbm_surface_queue_h queue);
82 } tbm_surface_queue_interface;
84 struct _tbm_surface_queue {
92 struct list_head list;
94 struct list_head destory_noti;
95 struct list_head dequeuable_noti;
96 struct list_head acquirable_noti;
97 struct list_head reset_noti;
100 pthread_cond_t free_cond;
101 pthread_cond_t dirty_cond;
103 const tbm_surface_queue_interface *impl;
106 //For external buffer allocation
107 tbm_surface_alloc_cb alloc_cb;
108 tbm_surface_free_cb free_cb;
113 _queue_node_create(void)
115 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
117 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
123 _queue_node_delete(queue_node *node)
125 LIST_DEL(&node->item_link);
126 LIST_DEL(&node->link);
131 _queue_is_empty(queue *queue)
133 if (LIST_IS_EMPTY(&queue->head))
140 _queue_node_push_back(queue *queue, queue_node *node)
142 LIST_ADDTAIL(&node->item_link, &queue->head);
147 _queue_node_push_front(queue *queue, queue_node *node)
149 LIST_ADD(&node->item_link, &queue->head);
154 _queue_node_pop_front(queue *queue)
156 queue_node *node = NULL;
158 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
160 LIST_DEL(&node->item_link);
167 _queue_node_pop(queue *queue, queue_node *node)
169 LIST_DEL(&node->item_link);
176 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
177 tbm_surface_h surface, int *out_type)
179 queue_node *node = NULL;
180 queue_node *tmp = NULL;
183 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
187 if (type & FREE_QUEUE) {
188 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
190 if (node->surface == surface) {
192 *out_type = FREE_QUEUE;
199 if (type & DIRTY_QUEUE) {
200 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
202 if (node->surface == surface) {
204 *out_type = DIRTY_QUEUE;
211 if (type & NODE_LIST) {
212 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
213 if (node->surface == surface) {
215 *out_type = NODE_LIST;
226 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
229 if (surface_queue->free_cb) {
230 surface_queue->free_cb(surface_queue,
231 surface_queue->alloc_cb_data,
235 tbm_surface_destroy(node->surface);
238 _queue_node_delete(node);
242 _queue_init(queue *queue)
244 LIST_INITHEAD(&queue->head);
250 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
253 TBM_RETURN_IF_FAIL(cb != NULL);
255 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
257 TBM_RETURN_IF_FAIL(item != NULL);
259 LIST_INITHEAD(&item->link);
263 LIST_ADDTAIL(&item->link, list);
267 _notify_remove(struct list_head *list,
268 tbm_surface_queue_notify_cb cb, void *data)
270 queue_notify *item = NULL, *tmp = NULL;
272 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
273 if (item->cb == cb && item->data == data) {
274 LIST_DEL(&item->link);
280 TBM_LOG("Cannot find notifiy\n");
284 _notify_remove_all(struct list_head *list)
286 queue_notify *item = NULL, *tmp = NULL;
288 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
289 LIST_DEL(&item->link);
295 _notify_emit(tbm_surface_queue_h surface_queue,
296 struct list_head *list)
298 queue_notify *item = NULL, *tmp = NULL;
300 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
301 item->cb(surface_queue, item->data);
306 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
307 tbm_surface_h surface)
309 queue_node *node = NULL;
311 node = _queue_node_create();
312 TBM_RETURN_IF_FAIL(node != NULL);
314 tbm_surface_internal_ref(surface);
315 node->surface = surface;
317 LIST_ADDTAIL(&node->link, &surface_queue->list);
318 _queue_node_push_back(&surface_queue->free_queue, node);
322 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
323 tbm_surface_h surface)
325 queue_node *node = NULL;
328 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
330 _queue_delete_node(surface_queue, node);
334 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
335 queue_node *node, int push_back)
338 _queue_node_push_back(&surface_queue->dirty_queue, node);
340 _queue_node_push_front(&surface_queue->dirty_queue, node);
344 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
346 queue_node *node = NULL;
348 if (_queue_is_empty(&surface_queue->free_queue)) {
349 if (surface_queue->impl && surface_queue->impl->need_attach)
350 surface_queue->impl->need_attach(surface_queue);
352 if (_queue_is_empty(&surface_queue->free_queue))
356 node = _queue_node_pop_front(&surface_queue->free_queue);
362 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
364 queue_node *node = NULL;
366 if (_queue_is_empty(&surface_queue->dirty_queue))
369 node = _queue_node_pop_front(&surface_queue->dirty_queue);
375 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
376 queue_node *node, int push_back)
379 _queue_node_push_back(&surface_queue->free_queue, node);
381 _queue_node_push_front(&surface_queue->free_queue, node);
385 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
387 int width, int height, int format,
388 const tbm_surface_queue_interface *impl, void *data)
390 TBM_RETURN_IF_FAIL(surface_queue != NULL);
391 TBM_RETURN_IF_FAIL(impl != NULL);
393 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
395 pthread_mutex_init(&surface_queue->lock, NULL);
396 pthread_cond_init(&surface_queue->free_cond, NULL);
397 pthread_cond_init(&surface_queue->dirty_cond, NULL);
399 surface_queue->queue_size = queue_size;
400 surface_queue->width = width;
401 surface_queue->height = height;
402 surface_queue->format = format;
403 surface_queue->impl = impl;
404 surface_queue->impl_data = data;
406 _queue_init(&surface_queue->free_queue);
407 _queue_init(&surface_queue->dirty_queue);
408 LIST_INITHEAD(&surface_queue->list);
410 LIST_INITHEAD(&surface_queue->destory_noti);
411 LIST_INITHEAD(&surface_queue->acquirable_noti);
412 LIST_INITHEAD(&surface_queue->dequeuable_noti);
413 LIST_INITHEAD(&surface_queue->reset_noti);
415 if (surface_queue->impl && surface_queue->impl->init)
416 surface_queue->impl->init(surface_queue);
419 tbm_surface_queue_error_e
420 tbm_surface_queue_add_destroy_cb(
421 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
424 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
425 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
427 pthread_mutex_lock(&surface_queue->lock);
429 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
431 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
433 pthread_mutex_unlock(&surface_queue->lock);
435 return TBM_SURFACE_QUEUE_ERROR_NONE;
438 tbm_surface_queue_error_e
439 tbm_surface_queue_remove_destroy_cb(
440 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
443 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
444 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
446 pthread_mutex_lock(&surface_queue->lock);
448 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
450 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
452 pthread_mutex_unlock(&surface_queue->lock);
454 return TBM_SURFACE_QUEUE_ERROR_NONE;
457 tbm_surface_queue_error_e
458 tbm_surface_queue_add_dequeuable_cb(
459 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
462 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
463 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
465 pthread_mutex_lock(&surface_queue->lock);
467 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
469 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
471 pthread_mutex_unlock(&surface_queue->lock);
473 return TBM_SURFACE_QUEUE_ERROR_NONE;
476 tbm_surface_queue_error_e
477 tbm_surface_queue_remove_dequeuable_cb(
478 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
481 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
482 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
484 pthread_mutex_lock(&surface_queue->lock);
486 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
488 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
490 pthread_mutex_unlock(&surface_queue->lock);
492 return TBM_SURFACE_QUEUE_ERROR_NONE;
495 tbm_surface_queue_error_e
496 tbm_surface_queue_add_acquirable_cb(
497 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
500 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
501 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
503 pthread_mutex_lock(&surface_queue->lock);
505 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
507 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
509 pthread_mutex_unlock(&surface_queue->lock);
511 return TBM_SURFACE_QUEUE_ERROR_NONE;
514 tbm_surface_queue_error_e
515 tbm_surface_queue_remove_acquirable_cb(
516 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
519 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
520 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
522 pthread_mutex_lock(&surface_queue->lock);
524 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
526 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
528 pthread_mutex_unlock(&surface_queue->lock);
530 return TBM_SURFACE_QUEUE_ERROR_NONE;
533 tbm_surface_queue_error_e
534 tbm_surface_queue_set_alloc_cb(
535 tbm_surface_queue_h surface_queue,
536 tbm_surface_alloc_cb alloc_cb,
537 tbm_surface_free_cb free_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 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
547 surface_queue->alloc_cb = alloc_cb;
548 surface_queue->free_cb = free_cb;
549 surface_queue->alloc_cb_data = data;
551 pthread_mutex_unlock(&surface_queue->lock);
553 return TBM_SURFACE_QUEUE_ERROR_NONE;
557 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
559 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
561 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
563 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
565 return surface_queue->width;
569 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
571 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
573 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
575 return surface_queue->height;
579 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
581 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
583 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
585 return surface_queue->format;
589 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
591 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
593 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
595 return surface_queue->queue_size;
598 tbm_surface_queue_error_e
599 tbm_surface_queue_add_reset_cb(
600 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
603 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
604 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
606 pthread_mutex_lock(&surface_queue->lock);
608 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
610 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
612 pthread_mutex_unlock(&surface_queue->lock);
614 return TBM_SURFACE_QUEUE_ERROR_NONE;
617 tbm_surface_queue_error_e
618 tbm_surface_queue_remove_reset_cb(
619 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
622 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
623 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
625 pthread_mutex_lock(&surface_queue->lock);
627 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
629 _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
631 pthread_mutex_unlock(&surface_queue->lock);
633 return TBM_SURFACE_QUEUE_ERROR_NONE;
636 tbm_surface_queue_error_e
637 tbm_surface_queue_enqueue(tbm_surface_queue_h
638 surface_queue, tbm_surface_h surface)
640 queue_node *node = NULL;
643 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
644 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
645 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
646 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
648 pthread_mutex_lock(&surface_queue->lock);
650 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
652 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
653 if (node == NULL || queue_type != NODE_LIST) {
654 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
656 pthread_mutex_unlock(&surface_queue->lock);
657 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
660 if (surface_queue->impl && surface_queue->impl->enqueue)
661 surface_queue->impl->enqueue(surface_queue, node);
663 _tbm_surface_queue_enqueue(surface_queue, node, 1);
665 if (_queue_is_empty(&surface_queue->dirty_queue)) {
666 pthread_mutex_unlock(&surface_queue->lock);
667 return TBM_SURFACE_QUEUE_ERROR_NONE;
670 pthread_mutex_unlock(&surface_queue->lock);
671 pthread_cond_signal(&surface_queue->dirty_cond);
673 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
675 return TBM_SURFACE_QUEUE_ERROR_NONE;
678 tbm_surface_queue_error_e
679 tbm_surface_queue_dequeue(tbm_surface_queue_h
680 surface_queue, tbm_surface_h *surface)
682 queue_node *node = NULL;
684 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
685 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
686 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
687 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
689 pthread_mutex_lock(&surface_queue->lock);
691 if (surface_queue->impl && surface_queue->impl->dequeue)
692 node = surface_queue->impl->dequeue(surface_queue);
694 node = _tbm_surface_queue_dequeue(surface_queue);
698 pthread_mutex_unlock(&surface_queue->lock);
699 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
702 if (node->surface == NULL) {
704 TBM_LOG("_queue_node_pop_front failed\n");
705 pthread_mutex_unlock(&surface_queue->lock);
706 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
709 *surface = node->surface;
711 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
713 pthread_mutex_unlock(&surface_queue->lock);
715 return TBM_SURFACE_QUEUE_ERROR_NONE;
719 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
721 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
723 pthread_mutex_lock(&surface_queue->lock);
725 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
727 if (_queue_is_empty(&surface_queue->free_queue)) {
728 if (surface_queue->impl && surface_queue->impl->need_attach)
729 surface_queue->impl->need_attach(surface_queue);
732 if (_queue_is_empty(&surface_queue->free_queue)) {
734 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
735 pthread_mutex_unlock(&surface_queue->lock);
739 pthread_mutex_unlock(&surface_queue->lock);
743 pthread_mutex_unlock(&surface_queue->lock);
748 tbm_surface_queue_error_e
749 tbm_surface_queue_release(tbm_surface_queue_h
750 surface_queue, tbm_surface_h surface)
752 queue_node *node = NULL;
755 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
756 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
757 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
758 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
760 pthread_mutex_lock(&surface_queue->lock);
762 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
764 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
765 if (node == NULL || queue_type != NODE_LIST) {
766 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
768 pthread_mutex_unlock(&surface_queue->lock);
769 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
772 if (surface_queue->impl && surface_queue->impl->release)
773 surface_queue->impl->release(surface_queue, node);
775 _tbm_surface_queue_release(surface_queue, node, 1);
777 if (_queue_is_empty(&surface_queue->free_queue)) {
778 pthread_mutex_unlock(&surface_queue->lock);
779 return TBM_SURFACE_QUEUE_ERROR_NONE;
782 pthread_mutex_unlock(&surface_queue->lock);
783 pthread_cond_signal(&surface_queue->free_cond);
785 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
787 return TBM_SURFACE_QUEUE_ERROR_NONE;
790 tbm_surface_queue_error_e
791 tbm_surface_queue_acquire(tbm_surface_queue_h
792 surface_queue, tbm_surface_h *surface)
794 queue_node *node = NULL;
796 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
797 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
798 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
799 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
801 pthread_mutex_lock(&surface_queue->lock);
803 if (surface_queue->impl && surface_queue->impl->acquire)
804 node = surface_queue->impl->acquire(surface_queue);
806 node = _tbm_surface_queue_acquire(surface_queue);
810 pthread_mutex_unlock(&surface_queue->lock);
811 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
814 if (node->surface == NULL) {
816 TBM_LOG("_queue_node_pop_front failed\n");
817 pthread_mutex_unlock(&surface_queue->lock);
818 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
821 *surface = node->surface;
823 TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
825 pthread_mutex_unlock(&surface_queue->lock);
827 return TBM_SURFACE_QUEUE_ERROR_NONE;
831 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
833 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
835 pthread_mutex_lock(&surface_queue->lock);
837 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
839 if (_queue_is_empty(&surface_queue->dirty_queue)) {
841 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
842 pthread_mutex_unlock(&surface_queue->lock);
846 pthread_mutex_unlock(&surface_queue->lock);
850 pthread_mutex_unlock(&surface_queue->lock);
856 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
858 queue_node *node = NULL, *tmp = NULL;
860 TBM_RETURN_IF_FAIL(surface_queue != NULL);
862 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
864 _notify_emit(surface_queue, &surface_queue->destory_noti);
866 if (surface_queue->impl && surface_queue->impl->destroy)
867 surface_queue->impl->destroy(surface_queue);
869 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
870 _queue_delete_node(surface_queue, node);
873 _notify_remove_all(&surface_queue->destory_noti);
874 _notify_remove_all(&surface_queue->acquirable_noti);
875 _notify_remove_all(&surface_queue->dequeuable_noti);
876 _notify_remove_all(&surface_queue->reset_noti);
878 pthread_mutex_destroy(&surface_queue->lock);
882 tbm_surface_queue_error_e
883 tbm_surface_queue_reset(tbm_surface_queue_h
884 surface_queue, int width, int height, int format)
886 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
887 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
889 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
891 queue_node *node = NULL, *tmp = NULL;
893 if (width == surface_queue->width && height == surface_queue->height &&
894 format == surface_queue->format)
895 return TBM_SURFACE_QUEUE_ERROR_NONE;
897 pthread_mutex_lock(&surface_queue->lock);
899 surface_queue->width = width;
900 surface_queue->height = height;
901 surface_queue->format = format;
903 /* Destory surface and Push to free_queue */
904 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
905 _queue_delete_node(surface_queue, node);
909 _queue_init(&surface_queue->free_queue);
910 _queue_init(&surface_queue->dirty_queue);
911 LIST_INITHEAD(&surface_queue->list);
913 if (surface_queue->impl && surface_queue->impl->reset)
914 surface_queue->impl->reset(surface_queue);
916 pthread_mutex_unlock(&surface_queue->lock);
917 pthread_cond_signal(&surface_queue->free_cond);
919 _notify_emit(surface_queue, &surface_queue->reset_noti);
921 return TBM_SURFACE_QUEUE_ERROR_NONE;
924 tbm_surface_queue_error_e
925 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
927 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
928 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
930 queue_node *node = NULL, *tmp = NULL;
932 pthread_mutex_lock(&surface_queue->lock);
934 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
936 /* Destory surface and Push to free_queue */
937 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
938 _queue_delete_node(surface_queue, node);
942 _queue_init(&surface_queue->free_queue);
943 _queue_init(&surface_queue->dirty_queue);
944 LIST_INITHEAD(&surface_queue->list);
946 if (surface_queue->impl && surface_queue->impl->reset)
947 surface_queue->impl->reset(surface_queue);
949 _notify_emit(surface_queue, &surface_queue->reset_noti);
951 pthread_mutex_unlock(&surface_queue->lock);
952 pthread_cond_signal(&surface_queue->free_cond);
954 return TBM_SURFACE_QUEUE_ERROR_NONE;
964 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
966 tbm_queue_default *data = surface_queue->impl_data;
968 data->num_attached = 0;
972 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
974 tbm_queue_default *data = surface_queue->impl_data;
976 data->num_attached = 0;
980 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
982 free(surface_queue->impl_data);
986 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
988 tbm_queue_default *data = surface_queue->impl_data;
989 tbm_surface_h surface;
991 if (data->queue_size == data->num_attached)
994 if (surface_queue->alloc_cb) {
995 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
996 TBM_RETURN_IF_FAIL(surface != NULL);
997 tbm_surface_internal_ref(surface);
999 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1000 surface_queue->height,
1001 surface_queue->format,
1003 TBM_RETURN_IF_FAIL(surface != NULL);
1006 _tbm_surface_queue_attach(surface_queue, surface);
1007 tbm_surface_internal_unref(surface);
1008 data->num_attached++;
1011 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1012 __tbm_queue_default_init,
1013 __tbm_queue_default_reset,
1014 __tbm_queue_default_destroy,
1015 __tbm_queue_default_need_attach,
1016 NULL, /*__tbm_queue_default_enqueue*/
1017 NULL, /*__tbm_queue_default_release*/
1018 NULL, /*__tbm_queue_default_dequeue*/
1019 NULL, /*__tbm_queue_default_acquire*/
1023 tbm_surface_queue_create(int queue_size, int width,
1024 int height, int format, int flags)
1026 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1027 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1028 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1029 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1031 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1032 sizeof(struct _tbm_surface_queue));
1033 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1035 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1037 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1038 sizeof(tbm_queue_default));
1040 free(surface_queue);
1044 data->queue_size = queue_size;
1045 data->flags = flags;
1046 _tbm_surface_queue_init(surface_queue,
1048 width, height, format,
1049 &tbm_queue_default_impl, data);
1051 return surface_queue;
1059 } tbm_queue_sequence;
1062 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1064 tbm_queue_sequence *data = surface_queue->impl_data;
1066 data->num_attached = 0;
1067 _queue_init(&data->dequeue_list);
1071 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1073 tbm_queue_sequence *data = surface_queue->impl_data;
1075 data->num_attached = 0;
1076 _queue_init(&data->dequeue_list);
1080 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1082 free(surface_queue->impl_data);
1086 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1088 tbm_queue_sequence *data = surface_queue->impl_data;
1089 tbm_surface_h surface;
1091 if (data->queue_size == data->num_attached)
1094 if (surface_queue->alloc_cb) {
1095 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1096 TBM_RETURN_IF_FAIL(surface != NULL);
1097 tbm_surface_internal_ref(surface);
1099 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1100 surface_queue->height,
1101 surface_queue->format,
1103 TBM_RETURN_IF_FAIL(surface != NULL);
1106 _tbm_surface_queue_attach(surface_queue, surface);
1107 tbm_surface_internal_unref(surface);
1108 data->num_attached++;
1112 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1115 tbm_queue_sequence *data = surface_queue->impl_data;
1116 queue_node *next = NULL;
1117 queue_node *tmp = NULL;
1119 node->priv_flags = 0;
1121 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1122 if (next->priv_flags)
1124 _queue_node_pop(&data->dequeue_list, next);
1125 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1130 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1133 tbm_queue_sequence *data = surface_queue->impl_data;
1134 queue_node *node = NULL;
1136 node = _tbm_surface_queue_dequeue(surface_queue);
1138 _queue_node_push_back(&data->dequeue_list, node);
1139 node->priv_flags = 1;
1145 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1146 __tbm_queue_sequence_init,
1147 __tbm_queue_sequence_reset,
1148 __tbm_queue_sequence_destroy,
1149 __tbm_queue_sequence_need_attach,
1150 __tbm_queue_sequence_enqueue,
1151 NULL, /*__tbm_queue_sequence_release*/
1152 __tbm_queue_sequence_dequeue,
1153 NULL, /*__tbm_queue_sequence_acquire*/
1157 tbm_surface_queue_sequence_create(int queue_size, int width,
1158 int height, int format, int flags)
1160 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1161 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1162 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1163 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1165 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1166 sizeof(struct _tbm_surface_queue));
1167 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1169 TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1171 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1172 sizeof(tbm_queue_sequence));
1174 free(surface_queue);
1178 data->queue_size = queue_size;
1179 data->flags = flags;
1180 _tbm_surface_queue_init(surface_queue,
1182 width, height, format,
1183 &tbm_queue_sequence_impl, data);
1185 return surface_queue;