1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
32 #include "tbm_bufmgr_int.h"
42 #define TBM_TRACE() TBM_LOG("[TRACE] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
52 struct list_head head;
53 struct list_head tail;
59 tbm_surface_h surface;
61 struct list_head item_link;
62 struct list_head link;
64 unsigned int priv_flags; /*for each queue*/
68 struct list_head link;
70 tbm_surface_queue_notify_cb cb;
74 typedef struct _tbm_surface_queue_interface {
75 void (*init)(tbm_surface_queue_h queue);
76 void (*reset)(tbm_surface_queue_h queue);
77 void (*destroy)(tbm_surface_queue_h queue);
78 void (*need_attach)(tbm_surface_queue_h queue);
80 void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
81 void (*release)(tbm_surface_queue_h queue, queue_node *node);
82 queue_node *(*dequeue)(tbm_surface_queue_h queue);
83 queue_node *(*acquire)(tbm_surface_queue_h queue);
84 } tbm_surface_queue_interface;
86 struct _tbm_surface_queue {
93 struct list_head list;
95 struct list_head destory_noti;
96 struct list_head dequeuable_noti;
97 struct list_head acquirable_noti;
98 struct list_head reset_noti;
100 tbm_surface_queue_notify_cb destroy_cb;
101 void *destroy_cb_data;
103 tbm_surface_queue_notify_cb dequeuable_cb;
104 void *dequeuable_cb_data;
106 tbm_surface_queue_notify_cb acquirable_cb;
107 void *acquirable_cb_data;
109 tbm_surface_queue_notify_cb reset_cb;
112 pthread_mutex_t lock;
113 pthread_cond_t free_cond;
114 pthread_cond_t dirty_cond;
116 const tbm_surface_queue_interface *impl;
121 _queue_node_create(void)
123 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
125 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
131 _queue_node_delete(queue_node *node)
134 tbm_surface_destroy(node->surface);
136 LIST_DEL(&node->item_link);
137 LIST_DEL(&node->link);
142 _queue_is_empty(queue *queue)
144 if (queue->head.next == &queue->tail)
151 _queue_node_push_back(queue *queue, queue_node *node)
153 LIST_ADDTAIL(&node->item_link, &queue->tail);
158 _queue_node_push_front(queue *queue, queue_node *node)
160 LIST_ADD(&node->item_link, &queue->head);
165 _queue_node_pop_front(queue *queue)
167 queue_node *node = NULL;
169 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
171 LIST_DEL(&node->item_link);
178 _queue_node_pop(queue *queue, queue_node *node)
180 LIST_DEL(&node->item_link);
187 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
188 tbm_surface_h surface, int *out_type)
190 queue_node *node = NULL;
191 queue_node *tmp = NULL;
194 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
198 if (type & FREE_QUEUE) {
199 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
201 if (node->surface == surface) {
203 *out_type = FREE_QUEUE;
210 if (type & DIRTY_QUEUE) {
211 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
213 if (node->surface == surface) {
215 *out_type = DIRTY_QUEUE;
222 if (type & NODE_LIST) {
223 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
224 if (node->surface == surface) {
226 *out_type = NODE_LIST;
237 _queue_init(queue *queue)
239 LIST_INITHEAD(&queue->head);
240 LIST_INITHEAD(&queue->tail);
241 LIST_ADDTAIL(&queue->head, &queue->tail);
246 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
249 TBM_RETURN_IF_FAIL(cb != NULL);
251 queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
253 TBM_RETURN_IF_FAIL(item != NULL);
255 LIST_INITHEAD(&item->link);
259 LIST_ADDTAIL(&item->link, list);
263 _notify_remove(struct list_head *list,
264 tbm_surface_queue_notify_cb cb, void *data)
266 queue_notify *item = NULL, *tmp = NULL;
268 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
269 if (item->cb == cb && item->data == data) {
270 LIST_DEL(&item->link);
276 TBM_LOG("Cannot find notifiy\n");
280 _notify_remove_all(struct list_head *list)
282 queue_notify *item = NULL, *tmp = NULL;
284 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
285 LIST_DEL(&item->link);
291 _notify_emit(tbm_surface_queue_h surface_queue,
292 struct list_head *list)
294 queue_notify *item = NULL, *tmp = NULL;
296 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
297 item->cb(surface_queue, item->data);
302 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
303 tbm_surface_h surface)
305 queue_node *node = NULL;
307 node = _queue_node_create();
308 TBM_RETURN_IF_FAIL(node != NULL);
310 tbm_surface_internal_ref(surface);
311 node->surface = surface;
313 LIST_ADDTAIL(&node->link, &surface_queue->list);
314 _queue_node_push_back(&surface_queue->free_queue, node);
318 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
319 tbm_surface_h surface)
321 queue_node *node = NULL;
324 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
326 _queue_node_delete(node);
330 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
331 queue_node *node, int push_back)
334 _queue_node_push_back(&surface_queue->dirty_queue, node);
336 _queue_node_push_front(&surface_queue->dirty_queue, node);
340 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
342 queue_node *node = NULL;
344 if (_queue_is_empty(&surface_queue->free_queue)) {
345 if (surface_queue->impl && surface_queue->impl->need_attach)
346 surface_queue->impl->need_attach(surface_queue);
348 if (_queue_is_empty(&surface_queue->free_queue))
352 node = _queue_node_pop_front(&surface_queue->free_queue);
358 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
360 queue_node *node = NULL;
362 if (_queue_is_empty(&surface_queue->dirty_queue))
365 node = _queue_node_pop_front(&surface_queue->dirty_queue);
371 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
372 queue_node *node, int push_back)
375 _queue_node_push_back(&surface_queue->free_queue, node);
377 _queue_node_push_front(&surface_queue->free_queue, node);
381 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
382 int width, int height, int format,
383 const tbm_surface_queue_interface *impl, void *data)
385 TBM_RETURN_IF_FAIL(surface_queue != NULL);
386 TBM_RETURN_IF_FAIL(impl != NULL);
388 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
390 pthread_mutex_init(&surface_queue->lock, NULL);
391 pthread_cond_init(&surface_queue->free_cond, NULL);
392 pthread_cond_init(&surface_queue->dirty_cond, NULL);
394 surface_queue->width = width;
395 surface_queue->height = height;
396 surface_queue->format = format;
397 surface_queue->impl = impl;
398 surface_queue->impl_data = data;
400 _queue_init(&surface_queue->free_queue);
401 _queue_init(&surface_queue->dirty_queue);
402 LIST_INITHEAD(&surface_queue->list);
404 LIST_INITHEAD(&surface_queue->destory_noti);
405 LIST_INITHEAD(&surface_queue->acquirable_noti);
406 LIST_INITHEAD(&surface_queue->dequeuable_noti);
407 LIST_INITHEAD(&surface_queue->reset_noti);
409 if (surface_queue->impl && surface_queue->impl->init)
410 surface_queue->impl->init(surface_queue);
413 tbm_surface_queue_error_e
414 tbm_surface_queue_set_destroy_cb(
415 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
418 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
419 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
421 pthread_mutex_lock(&surface_queue->lock);
423 surface_queue->destroy_cb = destroy_cb;
424 surface_queue->destroy_cb_data = data;
426 pthread_mutex_unlock(&surface_queue->lock);
428 return TBM_SURFACE_QUEUE_ERROR_NONE;
431 tbm_surface_queue_error_e
432 tbm_surface_queue_add_destroy_cb(
433 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
436 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
437 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
439 pthread_mutex_lock(&surface_queue->lock);
441 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
443 pthread_mutex_unlock(&surface_queue->lock);
445 return TBM_SURFACE_QUEUE_ERROR_NONE;
448 tbm_surface_queue_error_e
449 tbm_surface_queue_remove_destroy_cb(
450 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
453 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
454 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
456 pthread_mutex_lock(&surface_queue->lock);
458 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
460 pthread_mutex_unlock(&surface_queue->lock);
462 return TBM_SURFACE_QUEUE_ERROR_NONE;
465 tbm_surface_queue_error_e
466 tbm_surface_queue_set_dequeuable_cb(
467 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
470 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
471 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
473 pthread_mutex_lock(&surface_queue->lock);
475 surface_queue->dequeuable_cb = dequeuable_cb;
476 surface_queue->dequeuable_cb_data = data;
478 pthread_mutex_unlock(&surface_queue->lock);
480 return TBM_SURFACE_QUEUE_ERROR_NONE;
483 tbm_surface_queue_error_e
484 tbm_surface_queue_add_dequeuable_cb(
485 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
488 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
489 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
491 pthread_mutex_lock(&surface_queue->lock);
493 _notify_add(&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_remove_dequeuable_cb(
502 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_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 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_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_set_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 surface_queue->acquirable_cb = acquirable_cb;
528 surface_queue->acquirable_cb_data = data;
530 pthread_mutex_unlock(&surface_queue->lock);
532 return TBM_SURFACE_QUEUE_ERROR_NONE;
535 tbm_surface_queue_error_e
536 tbm_surface_queue_add_acquirable_cb(
537 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
540 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
541 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
543 pthread_mutex_lock(&surface_queue->lock);
545 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
547 pthread_mutex_unlock(&surface_queue->lock);
549 return TBM_SURFACE_QUEUE_ERROR_NONE;
552 tbm_surface_queue_error_e
553 tbm_surface_queue_remove_acquirable_cb(
554 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
557 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
558 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
560 pthread_mutex_lock(&surface_queue->lock);
562 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
564 pthread_mutex_unlock(&surface_queue->lock);
566 return TBM_SURFACE_QUEUE_ERROR_NONE;
570 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
572 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
574 return surface_queue->width;
578 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
580 return surface_queue->height;
584 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
586 return surface_queue->format;
589 tbm_surface_queue_error_e
590 tbm_surface_queue_set_reset_cb(
591 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
594 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
595 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
597 pthread_mutex_lock(&surface_queue->lock);
599 surface_queue->reset_cb = reset_cb;
600 surface_queue->reset_cb_data = data;
602 pthread_mutex_unlock(&surface_queue->lock);
604 return TBM_SURFACE_QUEUE_ERROR_NONE;
607 tbm_surface_queue_error_e
608 tbm_surface_queue_add_reset_cb(
609 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
612 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
613 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
615 pthread_mutex_lock(&surface_queue->lock);
617 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
619 pthread_mutex_unlock(&surface_queue->lock);
621 return TBM_SURFACE_QUEUE_ERROR_NONE;
624 tbm_surface_queue_error_e
625 tbm_surface_queue_remove_reset_cb(
626 tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
629 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
630 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
632 pthread_mutex_lock(&surface_queue->lock);
634 _notify_remove(&surface_queue->acquirable_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 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);
677 if (surface_queue->acquirable_cb)
678 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
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("_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 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 if (_queue_is_empty(&surface_queue->free_queue)) {
729 if (surface_queue->impl && surface_queue->impl->need_attach)
730 surface_queue->impl->need_attach(surface_queue);
733 if (_queue_is_empty(&surface_queue->free_queue)) {
735 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
736 pthread_mutex_unlock(&surface_queue->lock);
740 pthread_mutex_unlock(&surface_queue->lock);
744 pthread_mutex_unlock(&surface_queue->lock);
749 tbm_surface_queue_error_e
750 tbm_surface_queue_release(tbm_surface_queue_h
751 surface_queue, tbm_surface_h surface)
753 queue_node *node = NULL;
756 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
757 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
758 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
759 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
761 pthread_mutex_lock(&surface_queue->lock);
763 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
764 if (node == NULL || queue_type != NODE_LIST) {
765 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
767 pthread_mutex_unlock(&surface_queue->lock);
768 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
771 if (surface_queue->impl && surface_queue->impl->release)
772 surface_queue->impl->release(surface_queue, node);
774 _tbm_surface_queue_release(surface_queue, node, 1);
776 if (_queue_is_empty(&surface_queue->free_queue)) {
777 pthread_mutex_unlock(&surface_queue->lock);
778 return TBM_SURFACE_QUEUE_ERROR_NONE;
781 pthread_mutex_unlock(&surface_queue->lock);
782 pthread_cond_signal(&surface_queue->free_cond);
784 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
785 if (surface_queue->dequeuable_cb)
786 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
788 return TBM_SURFACE_QUEUE_ERROR_NONE;
791 tbm_surface_queue_error_e
792 tbm_surface_queue_acquire(tbm_surface_queue_h
793 surface_queue, tbm_surface_h *surface)
795 queue_node *node = NULL;
797 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
798 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
799 TBM_RETURN_VAL_IF_FAIL(surface != NULL,
800 TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
802 pthread_mutex_lock(&surface_queue->lock);
804 if (surface_queue->impl && surface_queue->impl->acquire)
805 node = surface_queue->impl->acquire(surface_queue);
807 node = _tbm_surface_queue_acquire(surface_queue);
811 pthread_mutex_unlock(&surface_queue->lock);
812 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
815 if (node->surface == NULL) {
817 TBM_LOG("_queue_node_pop_front failed\n");
818 pthread_mutex_unlock(&surface_queue->lock);
819 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
822 *surface = node->surface;
824 pthread_mutex_unlock(&surface_queue->lock);
826 return TBM_SURFACE_QUEUE_ERROR_NONE;
830 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
832 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
834 pthread_mutex_lock(&surface_queue->lock);
836 if (_queue_is_empty(&surface_queue->dirty_queue)) {
838 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
839 pthread_mutex_unlock(&surface_queue->lock);
843 pthread_mutex_unlock(&surface_queue->lock);
847 pthread_mutex_unlock(&surface_queue->lock);
853 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
855 queue_node *node = NULL, *tmp = NULL;
857 TBM_RETURN_IF_FAIL(surface_queue != NULL);
859 if (surface_queue->destroy_cb)
860 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
862 _notify_emit(surface_queue, &surface_queue->destory_noti);
864 if (surface_queue->impl && surface_queue->impl->destroy)
865 surface_queue->impl->destroy(surface_queue);
867 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
868 _queue_node_delete(node);
871 _notify_remove_all(&surface_queue->destory_noti);
872 _notify_remove_all(&surface_queue->acquirable_noti);
873 _notify_remove_all(&surface_queue->dequeuable_noti);
874 _notify_remove_all(&surface_queue->reset_noti);
876 pthread_mutex_destroy(&surface_queue->lock);
880 tbm_surface_queue_error_e
881 tbm_surface_queue_reset(tbm_surface_queue_h
882 surface_queue, int width, int height, int format)
884 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
885 TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
887 queue_node *node = NULL, *tmp = NULL;
889 if (width == surface_queue->width && height == surface_queue->height &&
890 format == surface_queue->format)
891 return TBM_SURFACE_QUEUE_ERROR_NONE;
893 pthread_mutex_lock(&surface_queue->lock);
895 surface_queue->width = width;
896 surface_queue->height = height;
897 surface_queue->format = format;
899 /* Destory surface and Push to free_queue */
900 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
901 _queue_node_delete(node);
905 _queue_init(&surface_queue->free_queue);
906 _queue_init(&surface_queue->dirty_queue);
907 LIST_INITHEAD(&surface_queue->list);
909 if (surface_queue->impl && surface_queue->impl->reset)
910 surface_queue->impl->reset(surface_queue);
912 pthread_mutex_unlock(&surface_queue->lock);
913 pthread_cond_signal(&surface_queue->free_cond);
915 _notify_emit(surface_queue, &surface_queue->reset_noti);
916 if (surface_queue->reset_cb)
917 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
919 return TBM_SURFACE_QUEUE_ERROR_NONE;
929 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
931 tbm_queue_default *data = surface_queue->impl_data;
933 data->num_attached = 0;
937 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
939 tbm_queue_default *data = surface_queue->impl_data;
941 data->num_attached = 0;
945 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
947 free(surface_queue->impl_data);
951 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
953 tbm_queue_default *data = surface_queue->impl_data;
954 tbm_surface_h surface;
956 if (data->queue_size == data->num_attached)
959 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
960 surface_queue->height,
961 surface_queue->format,
963 TBM_RETURN_IF_FAIL(surface != NULL);
964 _tbm_surface_queue_attach(surface_queue, surface);
965 tbm_surface_internal_unref(surface);
966 data->num_attached++;
969 static const tbm_surface_queue_interface tbm_queue_default_impl = {
970 __tbm_queue_default_init,
971 __tbm_queue_default_reset,
972 __tbm_queue_default_destroy,
973 __tbm_queue_default_need_attach,
974 NULL, /*__tbm_queue_default_enqueue*/
975 NULL, /*__tbm_queue_default_release*/
976 NULL, /*__tbm_queue_default_dequeue*/
977 NULL, /*__tbm_queue_default_acquire*/
981 tbm_surface_queue_create(int queue_size, int width,
982 int height, int format, int flags)
984 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
985 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
986 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
987 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
989 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
990 sizeof(struct _tbm_surface_queue));
991 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
993 tbm_queue_default *data = (tbm_queue_default *) calloc(1,
994 sizeof(tbm_queue_default));
1000 data->queue_size = queue_size;
1001 data->flags = flags;
1002 _tbm_surface_queue_init(surface_queue,
1003 width, height, format,
1004 &tbm_queue_default_impl, data);
1006 return surface_queue;
1014 } tbm_queue_sequence;
1017 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1019 tbm_queue_sequence *data = surface_queue->impl_data;
1021 data->num_attached = 0;
1022 _queue_init(&data->dequeue_list);
1026 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1028 tbm_queue_sequence *data = surface_queue->impl_data;
1030 data->num_attached = 0;
1031 _queue_init(&data->dequeue_list);
1035 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1037 free(surface_queue->impl_data);
1041 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1043 tbm_queue_sequence *data = surface_queue->impl_data;
1044 tbm_surface_h surface;
1046 if (data->queue_size == data->num_attached)
1049 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1050 surface_queue->height,
1051 surface_queue->format,
1053 TBM_RETURN_IF_FAIL(surface != NULL);
1054 _tbm_surface_queue_attach(surface_queue, surface);
1055 tbm_surface_internal_unref(surface);
1056 data->num_attached++;
1060 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1063 tbm_queue_sequence *data = surface_queue->impl_data;
1064 queue_node *next = NULL;
1065 queue_node *tmp = NULL;
1067 node->priv_flags = 0;
1069 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1070 if (next->priv_flags)
1072 _queue_node_pop(&data->dequeue_list, next);
1073 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1078 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1081 tbm_queue_sequence *data = surface_queue->impl_data;
1082 queue_node *node = NULL;
1084 node = _tbm_surface_queue_dequeue(surface_queue);
1086 _queue_node_push_back(&data->dequeue_list, node);
1087 node->priv_flags = 1;
1093 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1094 __tbm_queue_sequence_init,
1095 __tbm_queue_sequence_reset,
1096 __tbm_queue_sequence_destroy,
1097 __tbm_queue_sequence_need_attach,
1098 __tbm_queue_sequence_enqueue,
1099 NULL, /*__tbm_queue_sequence_release*/
1100 __tbm_queue_sequence_dequeue,
1101 NULL, /*__tbm_queue_sequence_acquire*/
1105 tbm_surface_queue_sequence_create(int queue_size, int width,
1106 int height, int format, int flags)
1108 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1109 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1110 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1111 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1113 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1114 sizeof(struct _tbm_surface_queue));
1115 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1117 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1118 sizeof(tbm_queue_sequence));
1120 free(surface_queue);
1124 data->queue_size = queue_size;
1125 data->flags = flags;
1126 _tbm_surface_queue_init(surface_queue,
1127 width, height, format,
1128 &tbm_queue_sequence_impl, data);
1130 return surface_queue;