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", __FUNCTION__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __FUNCTION__, __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;
120 static queue_node *_queue_node_create(void)
122 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
123 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
128 static void _queue_node_delete(queue_node * node)
131 tbm_surface_destroy(node->surface);
133 LIST_DEL(&node->item_link);
134 LIST_DEL(&node->link);
138 static int _queue_is_empty(queue * queue)
140 if (queue->head.next == &queue->tail)
146 static void _queue_node_push_back(queue * queue, queue_node * node)
148 LIST_ADDTAIL(&node->item_link, &queue->tail);
153 static void _queue_node_push_front(queue * queue, queue_node * node)
155 LIST_ADD(&node->item_link, &queue->head);
160 static queue_node *_queue_node_pop_front(queue * queue)
162 queue_node *node = NULL;
164 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
166 LIST_DEL(&node->item_link);
172 static queue_node *_queue_node_pop(queue * queue, queue_node* node)
174 LIST_DEL(&node->item_link);
180 static queue_node* _queue_get_node(tbm_surface_queue_h surface_queue, int type, tbm_surface_h surface, int *out_type)
182 queue_node *node = NULL;
183 queue_node *tmp = NULL;
186 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
190 if (type & FREE_QUEUE)
192 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
193 if (node->surface == surface)
195 if (out_type) *out_type = FREE_QUEUE;
201 if (type & DIRTY_QUEUE)
203 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head, item_link) {
204 if (node->surface == surface)
206 if (out_type) *out_type = DIRTY_QUEUE;
212 if (type & NODE_LIST)
214 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
215 if (node->surface == surface)
217 if (out_type) *out_type = NODE_LIST;
226 static void _queue_init(queue * queue)
228 LIST_INITHEAD(&queue->head);
229 LIST_INITHEAD(&queue->tail);
230 LIST_ADDTAIL(&queue->head, &queue->tail);
234 static void _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb, void* data)
236 TBM_RETURN_IF_FAIL(cb != NULL);
238 queue_notify *item = (queue_notify*)calloc(1, sizeof(queue_notify));
239 TBM_RETURN_IF_FAIL(item != NULL);
241 LIST_INITHEAD(&item->link);
245 LIST_ADDTAIL(&item->link, list);
248 static void _notify_remove(struct list_head *list, tbm_surface_queue_notify_cb cb, void* data)
250 queue_notify *item = NULL, *tmp = NULL;
252 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
253 if (item->cb == cb && item->data == data) {
254 LIST_DEL(&item->link);
260 TBM_LOG("Cannot find notifiy\n");
263 static void _notify_remove_all(struct list_head *list)
265 queue_notify *item = NULL, *tmp = NULL;
267 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
268 LIST_DEL(&item->link);
273 static void _notify_emit(tbm_surface_queue_h surface_queue, struct list_head *list)
275 queue_notify *item = NULL, *tmp = NULL;
277 LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
278 item->cb(surface_queue, item->data);
282 void _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
284 queue_node *node = NULL;
286 node = _queue_node_create();
287 TBM_RETURN_IF_FAIL(node != NULL);
289 tbm_surface_internal_ref(surface);
290 node->surface = surface;
292 LIST_ADDTAIL(&node->link, &surface_queue->list);
293 _queue_node_push_back(&surface_queue->free_queue, node);
296 void _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
298 queue_node *node = NULL;
301 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
303 _queue_node_delete(node);
306 void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, queue_node* node, int push_back)
309 _queue_node_push_back(&surface_queue->dirty_queue, node);
311 _queue_node_push_front(&surface_queue->dirty_queue, node);
314 queue_node* _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
316 queue_node *node = NULL;
318 if (_queue_is_empty(&surface_queue->free_queue)) {
319 if (surface_queue->impl && surface_queue->impl->need_attach)
320 surface_queue->impl->need_attach(surface_queue);
322 if (_queue_is_empty(&surface_queue->free_queue)) {
327 node = _queue_node_pop_front(&surface_queue->free_queue);
332 queue_node* _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
334 queue_node *node = NULL;
336 if (_queue_is_empty(&surface_queue->dirty_queue)) {
340 node = _queue_node_pop_front(&surface_queue->dirty_queue);
345 void _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, queue_node* node, int push_back)
348 _queue_node_push_back(&surface_queue->free_queue, node);
350 _queue_node_push_front(&surface_queue->free_queue, node);
353 void _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
354 int width, int height, int format,
355 const tbm_surface_queue_interface* impl, void *data)
357 TBM_RETURN_IF_FAIL(surface_queue != NULL);
358 TBM_RETURN_IF_FAIL(impl != NULL);
360 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
362 pthread_mutex_init(&surface_queue->lock, NULL);
363 pthread_cond_init(&surface_queue->free_cond, NULL);
364 pthread_cond_init(&surface_queue->dirty_cond, NULL);
366 surface_queue->width = width;
367 surface_queue->height = height;
368 surface_queue->format = format;
369 surface_queue->impl = impl;
370 surface_queue->impl_data = data;
372 _queue_init(&surface_queue->free_queue);
373 _queue_init(&surface_queue->dirty_queue);
374 LIST_INITHEAD(&surface_queue->list);
376 LIST_INITHEAD(&surface_queue->destory_noti);
377 LIST_INITHEAD(&surface_queue->acquirable_noti);
378 LIST_INITHEAD(&surface_queue->dequeuable_noti);
379 LIST_INITHEAD(&surface_queue->reset_noti);
381 if (surface_queue->impl && surface_queue->impl->init)
382 surface_queue->impl->init(surface_queue);
385 tbm_surface_queue_error_e tbm_surface_queue_set_destroy_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
387 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
389 pthread_mutex_lock(&surface_queue->lock);
391 surface_queue->destroy_cb = destroy_cb;
392 surface_queue->destroy_cb_data = data;
394 pthread_mutex_unlock(&surface_queue->lock);
396 return TBM_SURFACE_QUEUE_ERROR_NONE;
399 tbm_surface_queue_error_e tbm_surface_queue_add_destroy_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
401 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
403 pthread_mutex_lock(&surface_queue->lock);
405 _notify_add(&surface_queue->destory_noti, destroy_cb, data);
407 pthread_mutex_unlock(&surface_queue->lock);
409 return TBM_SURFACE_QUEUE_ERROR_NONE;
412 tbm_surface_queue_error_e tbm_surface_queue_remove_destroy_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
414 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
416 pthread_mutex_lock(&surface_queue->lock);
418 _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
420 pthread_mutex_unlock(&surface_queue->lock);
422 return TBM_SURFACE_QUEUE_ERROR_NONE;
425 tbm_surface_queue_error_e tbm_surface_queue_set_dequeuable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
427 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
429 pthread_mutex_lock(&surface_queue->lock);
431 surface_queue->dequeuable_cb = dequeuable_cb;
432 surface_queue->dequeuable_cb_data = data;
434 pthread_mutex_unlock(&surface_queue->lock);
436 return TBM_SURFACE_QUEUE_ERROR_NONE;
439 tbm_surface_queue_error_e tbm_surface_queue_add_dequeuable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
441 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
443 pthread_mutex_lock(&surface_queue->lock);
445 _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
447 pthread_mutex_unlock(&surface_queue->lock);
449 return TBM_SURFACE_QUEUE_ERROR_NONE;
452 tbm_surface_queue_error_e tbm_surface_queue_remove_dequeuable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
454 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
456 pthread_mutex_lock(&surface_queue->lock);
458 _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
460 pthread_mutex_unlock(&surface_queue->lock);
462 return TBM_SURFACE_QUEUE_ERROR_NONE;
465 tbm_surface_queue_error_e tbm_surface_queue_set_acquirable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
467 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
469 pthread_mutex_lock(&surface_queue->lock);
471 surface_queue->acquirable_cb = acquirable_cb;
472 surface_queue->acquirable_cb_data = data;
474 pthread_mutex_unlock(&surface_queue->lock);
476 return TBM_SURFACE_QUEUE_ERROR_NONE;
479 tbm_surface_queue_error_e tbm_surface_queue_add_acquirable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
481 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
483 pthread_mutex_lock(&surface_queue->lock);
485 _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
487 pthread_mutex_unlock(&surface_queue->lock);
489 return TBM_SURFACE_QUEUE_ERROR_NONE;
492 tbm_surface_queue_error_e tbm_surface_queue_remove_acquirable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
494 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
496 pthread_mutex_lock(&surface_queue->lock);
498 _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
500 pthread_mutex_unlock(&surface_queue->lock);
502 return TBM_SURFACE_QUEUE_ERROR_NONE;
505 int tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
507 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
509 return surface_queue->width;
512 int tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
514 return surface_queue->height;
517 int tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
519 return surface_queue->format;
522 tbm_surface_queue_error_e tbm_surface_queue_set_reset_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb, void *data)
524 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
526 pthread_mutex_lock(&surface_queue->lock);
528 surface_queue->reset_cb = reset_cb;
529 surface_queue->reset_cb_data = data;
531 pthread_mutex_unlock(&surface_queue->lock);
533 return TBM_SURFACE_QUEUE_ERROR_NONE;
536 tbm_surface_queue_error_e tbm_surface_queue_add_reset_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb, void *data)
538 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
540 pthread_mutex_lock(&surface_queue->lock);
542 _notify_add(&surface_queue->acquirable_noti, reset_cb, data);
544 pthread_mutex_unlock(&surface_queue->lock);
546 return TBM_SURFACE_QUEUE_ERROR_NONE;
549 tbm_surface_queue_error_e tbm_surface_queue_remove_reset_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb, void *data)
551 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
553 pthread_mutex_lock(&surface_queue->lock);
555 _notify_remove(&surface_queue->acquirable_noti, reset_cb, data);
557 pthread_mutex_unlock(&surface_queue->lock);
559 return TBM_SURFACE_QUEUE_ERROR_NONE;
562 tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
564 queue_node *node = NULL;
567 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
568 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
570 pthread_mutex_lock(&surface_queue->lock);
572 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
573 if (node == NULL || queue_type != NODE_LIST)
575 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type);
576 pthread_mutex_unlock(&surface_queue->lock);
577 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
580 if (surface_queue->impl && surface_queue->impl->enqueue)
581 surface_queue->impl->enqueue(surface_queue, node);
583 _tbm_surface_queue_enqueue(surface_queue, node, 1);
585 if (_queue_is_empty(&surface_queue->dirty_queue)) {
586 pthread_mutex_unlock(&surface_queue->lock);
587 return TBM_SURFACE_QUEUE_ERROR_NONE;
590 pthread_mutex_unlock(&surface_queue->lock);
591 pthread_cond_signal(&surface_queue->dirty_cond);
593 _notify_emit(surface_queue, &surface_queue->acquirable_noti);
594 if (surface_queue->acquirable_cb)
595 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
597 return TBM_SURFACE_QUEUE_ERROR_NONE;
600 tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue, tbm_surface_h * surface)
602 queue_node *node = NULL;
604 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
605 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
607 pthread_mutex_lock(&surface_queue->lock);
609 if (surface_queue->impl && surface_queue->impl->dequeue)
610 node = surface_queue->impl->dequeue(surface_queue);
612 node = _tbm_surface_queue_dequeue(surface_queue);
616 pthread_mutex_unlock(&surface_queue->lock);
617 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
620 if (node->surface == NULL) {
622 TBM_LOG("_queue_node_pop_front failed\n");
623 pthread_mutex_unlock(&surface_queue->lock);
624 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
627 *surface = node->surface;
629 pthread_mutex_unlock(&surface_queue->lock);
631 return TBM_SURFACE_QUEUE_ERROR_NONE;
634 int tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
636 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
638 pthread_mutex_lock(&surface_queue->lock);
640 if (_queue_is_empty(&surface_queue->free_queue)) {
641 if (surface_queue->impl && surface_queue->impl->need_attach)
642 surface_queue->impl->need_attach(surface_queue);
645 if (_queue_is_empty(&surface_queue->free_queue)) {
647 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
648 pthread_mutex_unlock(&surface_queue->lock);
652 pthread_mutex_unlock(&surface_queue->lock);
656 pthread_mutex_unlock(&surface_queue->lock);
661 tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
663 queue_node *node = NULL;
666 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
667 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
669 pthread_mutex_lock(&surface_queue->lock);
671 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
672 if (node == NULL || queue_type != NODE_LIST)
674 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type);
675 pthread_mutex_unlock(&surface_queue->lock);
676 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
679 if (surface_queue->impl && surface_queue->impl->release)
680 surface_queue->impl->release(surface_queue, node);
682 _tbm_surface_queue_release(surface_queue, node, 1);
684 if (_queue_is_empty(&surface_queue->free_queue)) {
685 pthread_mutex_unlock(&surface_queue->lock);
686 return TBM_SURFACE_QUEUE_ERROR_NONE;
689 pthread_mutex_unlock(&surface_queue->lock);
690 pthread_cond_signal(&surface_queue->free_cond);
692 _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
693 if (surface_queue->dequeuable_cb)
694 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
696 return TBM_SURFACE_QUEUE_ERROR_NONE;
699 tbm_surface_queue_error_e tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue, tbm_surface_h * surface)
701 queue_node *node = NULL;
703 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
704 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
706 pthread_mutex_lock(&surface_queue->lock);
708 if (surface_queue->impl && surface_queue->impl->acquire)
709 node = surface_queue->impl->acquire(surface_queue);
711 node = _tbm_surface_queue_acquire(surface_queue);
715 pthread_mutex_unlock(&surface_queue->lock);
716 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
719 if (node->surface == NULL) {
721 TBM_LOG("_queue_node_pop_front failed\n");
722 pthread_mutex_unlock(&surface_queue->lock);
723 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
726 *surface = node->surface;
728 pthread_mutex_unlock(&surface_queue->lock);
730 return TBM_SURFACE_QUEUE_ERROR_NONE;
733 int tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
735 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
737 pthread_mutex_lock(&surface_queue->lock);
739 if (_queue_is_empty(&surface_queue->dirty_queue)) {
741 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
742 pthread_mutex_unlock(&surface_queue->lock);
746 pthread_mutex_unlock(&surface_queue->lock);
750 pthread_mutex_unlock(&surface_queue->lock);
755 void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
757 queue_node *node = NULL, *tmp = NULL;
759 TBM_RETURN_IF_FAIL(surface_queue != NULL);
761 if (surface_queue->destroy_cb)
762 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
764 _notify_emit(surface_queue, &surface_queue->destory_noti);
766 if (surface_queue->impl && surface_queue->impl->destroy)
767 surface_queue->impl->destroy(surface_queue);
769 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
770 _queue_node_delete(node);
773 _notify_remove_all(&surface_queue->destory_noti);
774 _notify_remove_all(&surface_queue->acquirable_noti);
775 _notify_remove_all(&surface_queue->dequeuable_noti);
776 _notify_remove_all(&surface_queue->reset_noti);
778 pthread_mutex_destroy(&surface_queue->lock);
782 tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_queue, int width, int height, int format)
784 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
786 queue_node *node = NULL, *tmp = NULL;
788 if (width == surface_queue->width && height == surface_queue->height && format == surface_queue->format)
789 return TBM_SURFACE_QUEUE_ERROR_NONE;
791 pthread_mutex_lock(&surface_queue->lock);
793 surface_queue->width = width;
794 surface_queue->height = height;
795 surface_queue->format = format;
797 /* Destory surface and Push to free_queue */
798 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
800 _queue_node_delete(node);
804 _queue_init(&surface_queue->free_queue);
805 _queue_init(&surface_queue->dirty_queue);
806 LIST_INITHEAD(&surface_queue->list);
808 if (surface_queue->impl && surface_queue->impl->reset)
809 surface_queue->impl->reset(surface_queue);
811 pthread_mutex_unlock(&surface_queue->lock);
812 pthread_cond_signal(&surface_queue->free_cond);
814 _notify_emit(surface_queue, &surface_queue->reset_noti);
815 if (surface_queue->reset_cb)
816 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
818 return TBM_SURFACE_QUEUE_ERROR_NONE;
828 static void __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
830 tbm_queue_default* data = surface_queue->impl_data;
831 data->num_attached = 0;
834 static void __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
836 tbm_queue_default* data = surface_queue->impl_data;
837 data->num_attached = 0;
840 static void __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
842 free(surface_queue->impl_data);
845 static void __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
847 tbm_queue_default* data = surface_queue->impl_data;
848 tbm_surface_h surface;
850 if (data->queue_size == data->num_attached)
853 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
854 surface_queue->height,
855 surface_queue->format,
857 TBM_RETURN_IF_FAIL(surface != NULL);
858 _tbm_surface_queue_attach(surface_queue, surface);
859 tbm_surface_internal_unref(surface);
860 data->num_attached++;
863 static const tbm_surface_queue_interface tbm_queue_default_impl =
865 __tbm_queue_default_init,
866 __tbm_queue_default_reset,
867 __tbm_queue_default_destroy,
868 __tbm_queue_default_need_attach,
869 NULL, /*__tbm_queue_default_enqueue*/
870 NULL, /*__tbm_queue_default_release*/
871 NULL, /*__tbm_queue_default_dequeue*/
872 NULL, /*__tbm_queue_default_acquire*/
875 tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags)
877 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
878 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
879 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
880 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
882 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue));
883 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
885 tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default));
892 data->queue_size = queue_size;
894 _tbm_surface_queue_init(surface_queue,
895 width, height, format,
896 &tbm_queue_default_impl, data);
898 return surface_queue;
909 static void __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
911 tbm_queue_sequence* data = surface_queue->impl_data;
913 data->num_attached = 0;
914 _queue_init(&data->dequeue_list);
917 static void __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
919 tbm_queue_sequence* data = surface_queue->impl_data;
921 data->num_attached = 0;
922 _queue_init(&data->dequeue_list);
925 static void __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
927 free(surface_queue->impl_data);
930 static void __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
932 tbm_queue_sequence* data = surface_queue->impl_data;
933 tbm_surface_h surface;
935 if (data->queue_size == data->num_attached)
938 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
939 surface_queue->height,
940 surface_queue->format,
942 TBM_RETURN_IF_FAIL(surface != NULL);
943 _tbm_surface_queue_attach(surface_queue, surface);
944 tbm_surface_internal_unref(surface);
945 data->num_attached++;
948 static void __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue, queue_node* node)
950 tbm_queue_sequence* data = surface_queue->impl_data;
951 queue_node *next = NULL;
952 queue_node *tmp = NULL;
954 node->priv_flags = 0;
956 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
957 if (next->priv_flags) break;
958 _queue_node_pop(&data->dequeue_list, next);
959 _tbm_surface_queue_enqueue(surface_queue, next, 1);
963 static queue_node* __tbm_queue_sequence_dequeue(tbm_surface_queue_h surface_queue)
965 tbm_queue_sequence* data = surface_queue->impl_data;
966 queue_node* node = NULL;
968 node = _tbm_surface_queue_dequeue(surface_queue);
971 _queue_node_push_back(&data->dequeue_list, node);
972 node->priv_flags = 1;
978 static const tbm_surface_queue_interface tbm_queue_sequence_impl =
980 __tbm_queue_sequence_init,
981 __tbm_queue_sequence_reset,
982 __tbm_queue_sequence_destroy,
983 __tbm_queue_sequence_need_attach,
984 __tbm_queue_sequence_enqueue,
985 NULL, /*__tbm_queue_sequence_release*/
986 __tbm_queue_sequence_dequeue,
987 NULL, /*__tbm_queue_sequence_acquire*/
990 tbm_surface_queue_h tbm_surface_queue_sequence_create(int queue_size, int width, int height, int format, int flags)
992 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
993 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
994 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
995 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
997 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue));
998 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1000 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1, sizeof(tbm_queue_sequence));
1003 free(surface_queue);
1007 data->queue_size = queue_size;
1008 data->flags = flags;
1009 _tbm_surface_queue_init(surface_queue,
1010 width, height, format,
1011 &tbm_queue_sequence_impl, data);
1013 return surface_queue;