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 {
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 tbm_surface_queue_notify_cb destroy_cb;
102 void *destroy_cb_data;
104 tbm_surface_queue_notify_cb dequeuable_cb;
105 void *dequeuable_cb_data;
107 tbm_surface_queue_notify_cb acquirable_cb;
108 void *acquirable_cb_data;
110 tbm_surface_queue_notify_cb reset_cb;
113 pthread_mutex_t lock;
114 pthread_cond_t free_cond;
115 pthread_cond_t dirty_cond;
117 const tbm_surface_queue_interface *impl;
120 //For external buffer allocation
121 tbm_surface_alloc_cb alloc_cb;
122 tbm_surface_free_cb free_cb;
127 _queue_node_create(void)
129 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
131 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
137 _queue_node_delete(queue_node *node)
139 LIST_DEL(&node->item_link);
140 LIST_DEL(&node->link);
145 _queue_is_empty(queue *queue)
147 if (queue->head.next == &queue->tail)
154 _queue_node_push_back(queue *queue, queue_node *node)
156 LIST_ADDTAIL(&node->item_link, &queue->tail);
161 _queue_node_push_front(queue *queue, queue_node *node)
163 LIST_ADD(&node->item_link, &queue->head);
168 _queue_node_pop_front(queue *queue)
170 queue_node *node = NULL;
172 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
174 LIST_DEL(&node->item_link);
181 _queue_node_pop(queue *queue, queue_node *node)
183 LIST_DEL(&node->item_link);
190 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
191 tbm_surface_h surface, int *out_type)
193 queue_node *node = NULL;
194 queue_node *tmp = NULL;
197 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
201 if (type & FREE_QUEUE) {
202 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
204 if (node->surface == surface) {
206 *out_type = FREE_QUEUE;
213 if (type & DIRTY_QUEUE) {
214 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
216 if (node->surface == surface) {
218 *out_type = DIRTY_QUEUE;
225 if (type & NODE_LIST) {
226 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
227 if (node->surface == surface) {
229 *out_type = NODE_LIST;
240 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
243 if (surface_queue->free_cb) {
244 surface_queue->free_cb(surface_queue,
245 surface_queue->alloc_cb_data,
249 tbm_surface_destroy(node->surface);
252 _queue_node_delete(node);
256 _queue_init(queue *queue)
258 LIST_INITHEAD(&queue->head);
259 LIST_INITHEAD(&queue->tail);
260 LIST_ADDTAIL(&queue->head, &queue->tail);
265 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
268 TBM_RETURN_IF_FAIL(cb != NULL);
270 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
272 TBM_RETURN_IF_FAIL(item != NULL);
274 LIST_INITHEAD(&item->link);
278 LIST_ADDTAIL(&item->link, list);
282 _notify_remove(struct list_head *list,
283 tbm_surface_queue_notify_cb cb, void *data)
285 queue_notify *item = NULL, *tmp = NULL;
287 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
288 if (item->cb == cb && item->data == data) {
289 LIST_DEL(&item->link);
295 TBM_LOG("Cannot find notifiy\n");
299 _notify_remove_all(struct list_head *list)
301 queue_notify *item = NULL, *tmp = NULL;
303 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
304 LIST_DEL(&item->link);
310 _notify_emit(tbm_surface_queue_h surface_queue,
311 struct list_head *list)
313 queue_notify *item = NULL, *tmp = NULL;
315 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
316 item->cb(surface_queue, item->data);
321 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
322 tbm_surface_h surface)
324 queue_node *node = NULL;
326 node = _queue_node_create();
327 TBM_RETURN_IF_FAIL(node != NULL);
329 tbm_surface_internal_ref(surface);
330 node->surface = surface;
332 LIST_ADDTAIL(&node->link, &surface_queue->list);
333 _queue_node_push_back(&surface_queue->free_queue, node);
337 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
338 tbm_surface_h surface)
340 queue_node *node = NULL;
343 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
345 _queue_delete_node(surface_queue, node);
349 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
350 queue_node *node, int push_back)
353 _queue_node_push_back(&surface_queue->dirty_queue, node);
355 _queue_node_push_front(&surface_queue->dirty_queue, node);
359 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
361 queue_node *node = NULL;
363 if (_queue_is_empty(&surface_queue->free_queue)) {
364 if (surface_queue->impl && surface_queue->impl->need_attach)
365 surface_queue->impl->need_attach(surface_queue);
367 if (_queue_is_empty(&surface_queue->free_queue))
371 node = _queue_node_pop_front(&surface_queue->free_queue);
377 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
379 queue_node *node = NULL;
381 if (_queue_is_empty(&surface_queue->dirty_queue))
384 node = _queue_node_pop_front(&surface_queue->dirty_queue);
390 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
391 queue_node *node, int push_back)
394 _queue_node_push_back(&surface_queue->free_queue, node);
396 _queue_node_push_front(&surface_queue->free_queue, node);
400 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
402 int width, int height, int format,
403 const tbm_surface_queue_interface *impl, void *data)
405 TBM_RETURN_IF_FAIL(surface_queue != NULL);
406 TBM_RETURN_IF_FAIL(impl != NULL);
408 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
410 pthread_mutex_init(&surface_queue->lock, NULL);
411 pthread_cond_init(&surface_queue->free_cond, NULL);
412 pthread_cond_init(&surface_queue->dirty_cond, NULL);
414 surface_queue->queue_size = queue_size;
415 surface_queue->width = width;
416 surface_queue->height = height;
417 surface_queue->format = format;
418 surface_queue->impl = impl;
419 surface_queue->impl_data = data;
421 _queue_init(&surface_queue->free_queue);
422 _queue_init(&surface_queue->dirty_queue);
423 LIST_INITHEAD(&surface_queue->list);
425 LIST_INITHEAD(&surface_queue->destory_noti);
426 LIST_INITHEAD(&surface_queue->acquirable_noti);
427 LIST_INITHEAD(&surface_queue->dequeuable_noti);
428 LIST_INITHEAD(&surface_queue->reset_noti);
430 if (surface_queue->impl && surface_queue->impl->init)
431 surface_queue->impl->init(surface_queue);
434 tbm_surface_queue_error_e
435 tbm_surface_queue_set_destroy_cb(
436 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
439 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
440 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
442 pthread_mutex_lock(&surface_queue->lock);
444 surface_queue->destroy_cb = destroy_cb;
445 surface_queue->destroy_cb_data = data;
447 pthread_mutex_unlock(&surface_queue->lock);
449 return TBM_SURFACE_QUEUE_ERROR_NONE;
452 tbm_surface_queue_error_e
453 tbm_surface_queue_add_destroy_cb(
454 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
457 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
458 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
460 pthread_mutex_lock(&surface_queue->lock);
462 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
464 pthread_mutex_unlock(&surface_queue->lock);
466 return TBM_SURFACE_QUEUE_ERROR_NONE;
469 tbm_surface_queue_error_e
470 tbm_surface_queue_remove_destroy_cb(
471 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
474 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
475 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
477 pthread_mutex_lock(&surface_queue->lock);
479 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
481 pthread_mutex_unlock(&surface_queue->lock);
483 return TBM_SURFACE_QUEUE_ERROR_NONE;
486 tbm_surface_queue_error_e
487 tbm_surface_queue_set_dequeuable_cb(
488 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
491 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
492 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
494 pthread_mutex_lock(&surface_queue->lock);
496 surface_queue->dequeuable_cb = dequeuable_cb;
497 surface_queue->dequeuable_cb_data = data;
499 pthread_mutex_unlock(&surface_queue->lock);
501 return TBM_SURFACE_QUEUE_ERROR_NONE;
504 tbm_surface_queue_error_e
505 tbm_surface_queue_add_dequeuable_cb(
506 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
509 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
510 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
512 pthread_mutex_lock(&surface_queue->lock);
514 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
516 pthread_mutex_unlock(&surface_queue->lock);
518 return TBM_SURFACE_QUEUE_ERROR_NONE;
521 tbm_surface_queue_error_e
522 tbm_surface_queue_remove_dequeuable_cb(
523 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
526 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
527 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
529 pthread_mutex_lock(&surface_queue->lock);
531 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_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_acquirable_cb(
540 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_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 surface_queue->acquirable_cb = acquirable_cb;
549 surface_queue->acquirable_cb_data = data;
551 pthread_mutex_unlock(&surface_queue->lock);
553 return TBM_SURFACE_QUEUE_ERROR_NONE;
556 tbm_surface_queue_error_e
557 tbm_surface_queue_add_acquirable_cb(
558 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
561 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
562 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
564 pthread_mutex_lock(&surface_queue->lock);
566 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
568 pthread_mutex_unlock(&surface_queue->lock);
570 return TBM_SURFACE_QUEUE_ERROR_NONE;
573 tbm_surface_queue_error_e
574 tbm_surface_queue_remove_acquirable_cb(
575 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
578 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
579 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
581 pthread_mutex_lock(&surface_queue->lock);
583 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
585 pthread_mutex_unlock(&surface_queue->lock);
587 return TBM_SURFACE_QUEUE_ERROR_NONE;
590 tbm_surface_queue_error_e
591 tbm_surface_queue_set_alloc_cb(
592 tbm_surface_queue_h surface_queue,
593 tbm_surface_alloc_cb alloc_cb,
594 tbm_surface_free_cb free_cb,
597 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
598 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
600 pthread_mutex_lock(&surface_queue->lock);
602 surface_queue->alloc_cb = alloc_cb;
603 surface_queue->free_cb = free_cb;
604 surface_queue->alloc_cb_data = data;
606 pthread_mutex_unlock(&surface_queue->lock);
608 return TBM_SURFACE_QUEUE_ERROR_NONE;
612 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
614 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
616 return surface_queue->width;
620 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
622 return surface_queue->height;
626 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
628 return surface_queue->format;
632 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
634 return surface_queue->queue_size;
637 tbm_surface_queue_error_e
638 tbm_surface_queue_set_reset_cb(
639 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
642 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
643 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
645 pthread_mutex_lock(&surface_queue->lock);
647 surface_queue->reset_cb = reset_cb;
648 surface_queue->reset_cb_data = data;
650 pthread_mutex_unlock(&surface_queue->lock);
652 return TBM_SURFACE_QUEUE_ERROR_NONE;
655 tbm_surface_queue_error_e
656 tbm_surface_queue_add_reset_cb(
657 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
660 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
661 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
663 pthread_mutex_lock(&surface_queue->lock);
665 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
667 pthread_mutex_unlock(&surface_queue->lock);
669 return TBM_SURFACE_QUEUE_ERROR_NONE;
672 tbm_surface_queue_error_e
673 tbm_surface_queue_remove_reset_cb(
674 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
677 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
678 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
680 pthread_mutex_lock(&surface_queue->lock);
682 _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
684 pthread_mutex_unlock(&surface_queue->lock);
686 return TBM_SURFACE_QUEUE_ERROR_NONE;
689 tbm_surface_queue_error_e
690 tbm_surface_queue_enqueue(tbm_surface_queue_h
691 surface_queue, tbm_surface_h surface)
693 queue_node *node = NULL;
696 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
697 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
698 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
699 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
701 pthread_mutex_lock(&surface_queue->lock);
703 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
704 if (node == NULL || queue_type != NODE_LIST) {
705 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
707 pthread_mutex_unlock(&surface_queue->lock);
708 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
711 if (surface_queue->impl && surface_queue->impl->enqueue)
712 surface_queue->impl->enqueue(surface_queue, node);
714 _tbm_surface_queue_enqueue(surface_queue, node, 1);
716 if (_queue_is_empty(&surface_queue->dirty_queue)) {
717 pthread_mutex_unlock(&surface_queue->lock);
718 return TBM_SURFACE_QUEUE_ERROR_NONE;
721 pthread_mutex_unlock(&surface_queue->lock);
722 pthread_cond_signal(&surface_queue->dirty_cond);
724 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
725 if (surface_queue->acquirable_cb)
726 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
728 return TBM_SURFACE_QUEUE_ERROR_NONE;
731 tbm_surface_queue_error_e
732 tbm_surface_queue_dequeue(tbm_surface_queue_h
733 surface_queue, tbm_surface_h *surface)
735 queue_node *node = NULL;
737 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
738 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
739 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
740 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
742 pthread_mutex_lock(&surface_queue->lock);
744 if (surface_queue->impl && surface_queue->impl->dequeue)
745 node = surface_queue->impl->dequeue(surface_queue);
747 node = _tbm_surface_queue_dequeue(surface_queue);
751 pthread_mutex_unlock(&surface_queue->lock);
752 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
755 if (node->surface == NULL) {
757 TBM_LOG("_queue_node_pop_front failed\n");
758 pthread_mutex_unlock(&surface_queue->lock);
759 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
762 *surface = node->surface;
764 pthread_mutex_unlock(&surface_queue->lock);
766 return TBM_SURFACE_QUEUE_ERROR_NONE;
770 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
772 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
774 pthread_mutex_lock(&surface_queue->lock);
776 if (_queue_is_empty(&surface_queue->free_queue)) {
777 if (surface_queue->impl && surface_queue->impl->need_attach)
778 surface_queue->impl->need_attach(surface_queue);
781 if (_queue_is_empty(&surface_queue->free_queue)) {
783 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
784 pthread_mutex_unlock(&surface_queue->lock);
788 pthread_mutex_unlock(&surface_queue->lock);
792 pthread_mutex_unlock(&surface_queue->lock);
797 tbm_surface_queue_error_e
798 tbm_surface_queue_release(tbm_surface_queue_h
799 surface_queue, tbm_surface_h surface)
801 queue_node *node = NULL;
804 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
805 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
806 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
807 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
809 pthread_mutex_lock(&surface_queue->lock);
811 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
812 if (node == NULL || queue_type != NODE_LIST) {
813 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
815 pthread_mutex_unlock(&surface_queue->lock);
816 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
819 if (surface_queue->impl && surface_queue->impl->release)
820 surface_queue->impl->release(surface_queue, node);
822 _tbm_surface_queue_release(surface_queue, node, 1);
824 if (_queue_is_empty(&surface_queue->free_queue)) {
825 pthread_mutex_unlock(&surface_queue->lock);
826 return TBM_SURFACE_QUEUE_ERROR_NONE;
829 pthread_mutex_unlock(&surface_queue->lock);
830 pthread_cond_signal(&surface_queue->free_cond);
832 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
833 if (surface_queue->dequeuable_cb)
834 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
836 return TBM_SURFACE_QUEUE_ERROR_NONE;
839 tbm_surface_queue_error_e
840 tbm_surface_queue_acquire(tbm_surface_queue_h
841 surface_queue, tbm_surface_h *surface)
843 queue_node *node = NULL;
845 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
846 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
847 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
848 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
850 pthread_mutex_lock(&surface_queue->lock);
852 if (surface_queue->impl && surface_queue->impl->acquire)
853 node = surface_queue->impl->acquire(surface_queue);
855 node = _tbm_surface_queue_acquire(surface_queue);
859 pthread_mutex_unlock(&surface_queue->lock);
860 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
863 if (node->surface == NULL) {
865 TBM_LOG("_queue_node_pop_front failed\n");
866 pthread_mutex_unlock(&surface_queue->lock);
867 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
870 *surface = node->surface;
872 pthread_mutex_unlock(&surface_queue->lock);
874 return TBM_SURFACE_QUEUE_ERROR_NONE;
878 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
880 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
882 pthread_mutex_lock(&surface_queue->lock);
884 if (_queue_is_empty(&surface_queue->dirty_queue)) {
886 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
887 pthread_mutex_unlock(&surface_queue->lock);
891 pthread_mutex_unlock(&surface_queue->lock);
895 pthread_mutex_unlock(&surface_queue->lock);
901 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
903 queue_node *node = NULL, *tmp = NULL;
905 TBM_RETURN_IF_FAIL(surface_queue != NULL);
907 if (surface_queue->destroy_cb)
908 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
910 _notify_emit(surface_queue, &surface_queue->destory_noti);
912 if (surface_queue->impl && surface_queue->impl->destroy)
913 surface_queue->impl->destroy(surface_queue);
915 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
916 _queue_delete_node(surface_queue, node);
919 _notify_remove_all(&surface_queue->destory_noti);
920 _notify_remove_all(&surface_queue->acquirable_noti);
921 _notify_remove_all(&surface_queue->dequeuable_noti);
922 _notify_remove_all(&surface_queue->reset_noti);
924 pthread_mutex_destroy(&surface_queue->lock);
928 tbm_surface_queue_error_e
929 tbm_surface_queue_reset(tbm_surface_queue_h
930 surface_queue, int width, int height, int format)
932 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
933 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
935 queue_node *node = NULL, *tmp = NULL;
937 if (width == surface_queue->width && height == surface_queue->height &&
938 format == surface_queue->format)
939 return TBM_SURFACE_QUEUE_ERROR_NONE;
941 pthread_mutex_lock(&surface_queue->lock);
943 surface_queue->width = width;
944 surface_queue->height = height;
945 surface_queue->format = format;
947 /* Destory surface and Push to free_queue */
948 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
949 _queue_delete_node(surface_queue, node);
953 _queue_init(&surface_queue->free_queue);
954 _queue_init(&surface_queue->dirty_queue);
955 LIST_INITHEAD(&surface_queue->list);
957 if (surface_queue->impl && surface_queue->impl->reset)
958 surface_queue->impl->reset(surface_queue);
960 pthread_mutex_unlock(&surface_queue->lock);
961 pthread_cond_signal(&surface_queue->free_cond);
963 _notify_emit(surface_queue, &surface_queue->reset_noti);
964 if (surface_queue->reset_cb)
965 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
967 return TBM_SURFACE_QUEUE_ERROR_NONE;
970 tbm_surface_queue_error_e
971 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
973 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
974 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
976 queue_node *node = NULL, *tmp = NULL;
978 pthread_mutex_lock(&surface_queue->lock);
980 /* Destory surface and Push to free_queue */
981 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
982 _queue_delete_node(surface_queue, node);
986 _queue_init(&surface_queue->free_queue);
987 _queue_init(&surface_queue->dirty_queue);
988 LIST_INITHEAD(&surface_queue->list);
990 if (surface_queue->impl && surface_queue->impl->reset)
991 surface_queue->impl->reset(surface_queue);
993 _notify_emit(surface_queue, &surface_queue->reset_noti);
994 if (surface_queue->reset_cb)
995 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
997 pthread_mutex_unlock(&surface_queue->lock);
998 pthread_cond_signal(&surface_queue->free_cond);
1000 return TBM_SURFACE_QUEUE_ERROR_NONE;
1007 } tbm_queue_default;
1010 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1012 tbm_queue_default *data = surface_queue->impl_data;
1014 data->num_attached = 0;
1018 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1020 tbm_queue_default *data = surface_queue->impl_data;
1022 data->num_attached = 0;
1026 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1028 free(surface_queue->impl_data);
1032 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1034 tbm_queue_default *data = surface_queue->impl_data;
1035 tbm_surface_h surface;
1037 if (data->queue_size == data->num_attached)
1040 if (surface_queue->alloc_cb) {
1041 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1042 TBM_RETURN_IF_FAIL(surface != NULL);
1043 tbm_surface_internal_ref(surface);
1045 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1046 surface_queue->height,
1047 surface_queue->format,
1049 TBM_RETURN_IF_FAIL(surface != NULL);
1052 _tbm_surface_queue_attach(surface_queue, surface);
1053 tbm_surface_internal_unref(surface);
1054 data->num_attached++;
1057 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1058 __tbm_queue_default_init,
1059 __tbm_queue_default_reset,
1060 __tbm_queue_default_destroy,
1061 __tbm_queue_default_need_attach,
1062 NULL, /*__tbm_queue_default_enqueue*/
1063 NULL, /*__tbm_queue_default_release*/
1064 NULL, /*__tbm_queue_default_dequeue*/
1065 NULL, /*__tbm_queue_default_acquire*/
1069 tbm_surface_queue_create(int queue_size, int width,
1070 int height, int format, int flags)
1072 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1073 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1074 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1075 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1077 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1078 sizeof(struct _tbm_surface_queue));
1079 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1081 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1082 sizeof(tbm_queue_default));
1084 free(surface_queue);
1088 data->queue_size = queue_size;
1089 data->flags = flags;
1090 _tbm_surface_queue_init(surface_queue,
1092 width, height, format,
1093 &tbm_queue_default_impl, data);
1095 return surface_queue;
1103 } tbm_queue_sequence;
1106 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1108 tbm_queue_sequence *data = surface_queue->impl_data;
1110 data->num_attached = 0;
1111 _queue_init(&data->dequeue_list);
1115 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1117 tbm_queue_sequence *data = surface_queue->impl_data;
1119 data->num_attached = 0;
1120 _queue_init(&data->dequeue_list);
1124 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1126 free(surface_queue->impl_data);
1130 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1132 tbm_queue_sequence *data = surface_queue->impl_data;
1133 tbm_surface_h surface;
1135 if (data->queue_size == data->num_attached)
1138 if (surface_queue->alloc_cb) {
1139 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1140 TBM_RETURN_IF_FAIL(surface != NULL);
1141 tbm_surface_internal_ref(surface);
1143 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1144 surface_queue->height,
1145 surface_queue->format,
1147 TBM_RETURN_IF_FAIL(surface != NULL);
1150 _tbm_surface_queue_attach(surface_queue, surface);
1151 tbm_surface_internal_unref(surface);
1152 data->num_attached++;
1156 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1159 tbm_queue_sequence *data = surface_queue->impl_data;
1160 queue_node *next = NULL;
1161 queue_node *tmp = NULL;
1163 node->priv_flags = 0;
1165 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1166 if (next->priv_flags)
1168 _queue_node_pop(&data->dequeue_list, next);
1169 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1174 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1177 tbm_queue_sequence *data = surface_queue->impl_data;
1178 queue_node *node = NULL;
1180 node = _tbm_surface_queue_dequeue(surface_queue);
1182 _queue_node_push_back(&data->dequeue_list, node);
1183 node->priv_flags = 1;
1189 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1190 __tbm_queue_sequence_init,
1191 __tbm_queue_sequence_reset,
1192 __tbm_queue_sequence_destroy,
1193 __tbm_queue_sequence_need_attach,
1194 __tbm_queue_sequence_enqueue,
1195 NULL, /*__tbm_queue_sequence_release*/
1196 __tbm_queue_sequence_dequeue,
1197 NULL, /*__tbm_queue_sequence_acquire*/
1201 tbm_surface_queue_sequence_create(int queue_size, int width,
1202 int height, int format, int flags)
1204 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1205 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1206 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1207 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1209 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1210 sizeof(struct _tbm_surface_queue));
1211 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1213 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1214 sizeof(tbm_queue_sequence));
1216 free(surface_queue);
1220 data->queue_size = queue_size;
1221 data->flags = flags;
1222 _tbm_surface_queue_init(surface_queue,
1224 width, height, format,
1225 &tbm_queue_sequence_impl, data);
1227 return surface_queue;