X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftbm_surface_queue.c;h=1dadcb000c0258d107568b326400a0a9094289d8;hb=bd2104fffed8a422aeef711893b8e458a2aea197;hp=a77b285eea6da64b839e4485381237913370b431;hpb=feb49df7c99d67379f31845b82d83781b1158b0a;p=platform%2Fcore%2Fuifw%2Flibtbm.git diff --git a/src/tbm_surface_queue.c b/src/tbm_surface_queue.c index a77b285..1dadcb0 100644 --- a/src/tbm_surface_queue.c +++ b/src/tbm_surface_queue.c @@ -106,6 +106,13 @@ typedef struct { void *data; } queue_notify; +typedef struct { + struct list_head link; + + tbm_surface_queue_trace_cb cb; + void *data; +} queue_trace; + typedef struct _tbm_surface_queue_interface { void (*init)(tbm_surface_queue_h queue); void (*reset)(tbm_surface_queue_h queue); @@ -133,8 +140,10 @@ struct _tbm_surface_queue { struct list_head destory_noti; struct list_head dequeuable_noti; struct list_head dequeue_noti; + struct list_head can_dequeue_noti; struct list_head acquirable_noti; struct list_head reset_noti; + struct list_head trace_noti; pthread_mutex_t lock; pthread_cond_t free_cond; @@ -162,7 +171,7 @@ _tbm_surf_queue_mutex_init(void) return true; if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) { - TBM_LOG_E("fail: tbm_surf_queue mutex init\n"); + TBM_LOG_E("fail: pthread_mutex_init\n"); return false; } @@ -171,16 +180,18 @@ _tbm_surf_queue_mutex_init(void) return true; } -void +static void _tbm_surf_queue_mutex_lock(void) { - if (!_tbm_surf_queue_mutex_init()) + if (!_tbm_surf_queue_mutex_init()) { + TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n"); return; + } pthread_mutex_lock(&tbm_surf_queue_lock); } -void +static void _tbm_surf_queue_mutex_unlock(void) { pthread_mutex_unlock(&tbm_surf_queue_lock); @@ -205,22 +216,33 @@ _deinit_tbm_surf_queue_bufmgr(void) static int _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue) { - tbm_surface_queue_h old_data = NULL, tmp = NULL; + tbm_surface_queue_h old_data = NULL; - if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) { - TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue); + if (surface_queue == NULL) { + TBM_LOG_E("error: surface_queue is NULL.\n"); return 0; } - if (!LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) { - LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surf_queue_bufmgr->surf_queue_list, item_link) { - if (old_data == surface_queue) { - TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue); - return 1; - } + if (g_surf_queue_bufmgr == NULL) { + TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n"); + return 0; + } + + if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) { + TBM_LOG_E("error: surf_queue_list is empty\n"); + return 0; + } + + LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list, + item_link) { + if (old_data == surface_queue) { + TBM_TRACE("tbm_surface_queue(%p)\n", surface_queue); + return 1; } } - TBM_TRACE("error: tbm_surface_queue(%p)\n", surface_queue); + + TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue); + return 0; } @@ -268,11 +290,14 @@ _queue_node_push_front(queue *queue, queue_node *node) static queue_node * _queue_node_pop_front(queue *queue) { - queue_node *node = NULL; + queue_node *node; + + if (!queue->head.next) return NULL; + if (!queue->count) return NULL; node = LIST_ENTRY(queue_node, queue->head.next, item_link); - LIST_DEL(&node->item_link); + LIST_DELINIT(&node->item_link); queue->count--; return node; @@ -281,7 +306,7 @@ _queue_node_pop_front(queue *queue) static queue_node * _queue_node_pop(queue *queue, queue_node *node) { - LIST_DEL(&node->item_link); + LIST_DELINIT(&node->item_link); queue->count--; return node; @@ -292,7 +317,6 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type, tbm_surface_h surface, int *out_type) { queue_node *node = NULL; - queue_node *tmp = NULL; if (type == 0) type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST; @@ -300,7 +324,7 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type, *out_type = 0; if (type & FREE_QUEUE) { - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, + LIST_FOR_EACH_ENTRY(node, &surface_queue->free_queue.head, item_link) { if (node->surface == surface) { if (out_type) @@ -312,7 +336,7 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type, } if (type & DIRTY_QUEUE) { - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head, + LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head, item_link) { if (node->surface == surface) { if (out_type) @@ -324,7 +348,7 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type, } if (type & NODE_LIST) { - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) { if (node->surface == surface) { if (out_type) *out_type = NODE_LIST; @@ -334,6 +358,8 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type, } } + TBM_LOG_E("fail to get the queue_node.\n"); + return NULL; } @@ -382,7 +408,7 @@ static void _notify_remove(struct list_head *list, tbm_surface_queue_notify_cb cb, void *data) { - queue_notify *item = NULL, *tmp = NULL; + queue_notify *item = NULL, *tmp; LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) { if (item->cb == cb && item->data == data) { @@ -398,7 +424,7 @@ _notify_remove(struct list_head *list, static void _notify_remove_all(struct list_head *list) { - queue_notify *item = NULL, *tmp = NULL; + queue_notify *item = NULL, *tmp; LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) { LIST_DEL(&item->link); @@ -410,21 +436,84 @@ static void _notify_emit(tbm_surface_queue_h surface_queue, struct list_head *list) { - queue_notify *item = NULL, *tmp = NULL; + queue_notify *item = NULL, *tmp;; - LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) { + /* + The item->cb is the outside function of the libtbm. + The tbm user may/can remove the item of the list, + so we have to use the LIST_FOR_EACH_ENTRY_SAFE. + */ + LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) item->cb(surface_queue, item->data); +} + +static void +_trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb, + void *data) +{ + TBM_RETURN_IF_FAIL(cb != NULL); + + queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace)); + + TBM_RETURN_IF_FAIL(item != NULL); + + LIST_INITHEAD(&item->link); + item->cb = cb; + item->data = data; + + LIST_ADDTAIL(&item->link, list); +} + +static void +_trace_remove(struct list_head *list, + tbm_surface_queue_trace_cb cb, void *data) +{ + queue_trace *item = NULL, *tmp; + + LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) { + if (item->cb == cb && item->data == data) { + LIST_DEL(&item->link); + free(item); + return; + } + } + + TBM_LOG_E("Cannot find notifiy\n"); +} + +static void +_trace_remove_all(struct list_head *list) +{ + queue_trace *item = NULL, *tmp; + + LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) { + LIST_DEL(&item->link); + free(item); } } +static void +_trace_emit(tbm_surface_queue_h surface_queue, + struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace) +{ + queue_trace *item = NULL, *tmp;; + + /* + The item->cb is the outside function of the libtbm. + The tbm user may/can remove the item of the list, + so we have to use the LIST_FOR_EACH_ENTRY_SAFE. + */ + LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) + item->cb(surface_queue, surface, trace, item->data); +} + static int _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type) { queue_node *node = NULL; - queue_node *tmp = NULL; int count = 0; - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) { if (node->type == type) count++; } @@ -432,11 +521,11 @@ _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_ return count; } -void +static void _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - queue_node *node = NULL; + queue_node *node; node = _queue_node_create(); TBM_RETURN_IF_FAIL(node != NULL); @@ -449,11 +538,11 @@ _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue, _queue_node_push_back(&surface_queue->free_queue, node); } -void +static void _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - queue_node *node = NULL; + queue_node *node; int queue_type; node = _queue_get_node(surface_queue, 0, surface, &queue_type); @@ -463,7 +552,7 @@ _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, } } -void +static void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, queue_node *node, int push_back) { @@ -473,28 +562,20 @@ _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, _queue_node_push_front(&surface_queue->dirty_queue, node); } -queue_node * +static queue_node * _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue) { - queue_node *node = NULL; - - if (_queue_is_empty(&surface_queue->free_queue)) { - if (surface_queue->impl && surface_queue->impl->need_attach) - surface_queue->impl->need_attach(surface_queue); - - if (_queue_is_empty(&surface_queue->free_queue)) - return NULL; - } + queue_node *node; node = _queue_node_pop_front(&surface_queue->free_queue); return node; } -queue_node * +static queue_node * _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue) { - queue_node *node = NULL; + queue_node *node; if (_queue_is_empty(&surface_queue->dirty_queue)) return NULL; @@ -504,7 +585,7 @@ _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue) return node; } -void +static void _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, queue_node *node, int push_back) { @@ -514,7 +595,7 @@ _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, _queue_node_push_front(&surface_queue->free_queue, node); } -void +static void _tbm_surface_queue_init(tbm_surface_queue_h surface_queue, int queue_size, int width, int height, int format, @@ -523,8 +604,6 @@ _tbm_surface_queue_init(tbm_surface_queue_h surface_queue, TBM_RETURN_IF_FAIL(surface_queue != NULL); TBM_RETURN_IF_FAIL(impl != NULL); - memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue)); - if (!g_surf_queue_bufmgr) _init_tbm_surf_queue_bufmgr(); @@ -544,10 +623,12 @@ _tbm_surface_queue_init(tbm_surface_queue_h surface_queue, LIST_INITHEAD(&surface_queue->list); LIST_INITHEAD(&surface_queue->destory_noti); - LIST_INITHEAD(&surface_queue->acquirable_noti); LIST_INITHEAD(&surface_queue->dequeuable_noti); LIST_INITHEAD(&surface_queue->dequeue_noti); + LIST_INITHEAD(&surface_queue->can_dequeue_noti); + LIST_INITHEAD(&surface_queue->acquirable_noti); LIST_INITHEAD(&surface_queue->reset_noti); + LIST_INITHEAD(&surface_queue->trace_noti); if (surface_queue->impl && surface_queue->impl->init) surface_queue->impl->init(surface_queue); @@ -694,6 +775,52 @@ tbm_surface_queue_remove_dequeue_cb( } tbm_surface_queue_error_e +tbm_surface_queue_add_can_dequeue_cb( + tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb, + void *data) +{ + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); + + _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data); + + pthread_mutex_unlock(&surface_queue->lock); + + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +tbm_surface_queue_error_e +tbm_surface_queue_remove_can_dequeue_cb( + tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb, + void *data) +{ + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); + + _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data); + + pthread_mutex_unlock(&surface_queue->lock); + + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +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) @@ -740,6 +867,52 @@ tbm_surface_queue_remove_acquirable_cb( } tbm_surface_queue_error_e +tbm_surface_queue_add_trace_cb( + tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb, + void *data) +{ + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); + + _trace_add(&surface_queue->trace_noti, trace_cb, data); + + pthread_mutex_unlock(&surface_queue->lock); + + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +tbm_surface_queue_error_e +tbm_surface_queue_remove_trace_cb( + tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb, + void *data) +{ + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); + + _trace_remove(&surface_queue->trace_noti, trace_cb, data); + + pthread_mutex_unlock(&surface_queue->lock); + + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +tbm_surface_queue_error_e tbm_surface_queue_set_alloc_cb( tbm_surface_queue_h surface_queue, tbm_surface_alloc_cb alloc_cb, @@ -888,7 +1061,7 @@ tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - queue_node *node = NULL; + queue_node *node; int queue_type; _tbm_surf_queue_mutex_lock(); @@ -907,12 +1080,16 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h node = _queue_get_node(surface_queue, 0, surface, &queue_type); if (node == NULL || queue_type != NODE_LIST) { - TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", + TBM_LOG_E("tbm_surface_queue_enqueue::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n", node, queue_type); pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; + + if (!node) + return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE; + else + return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST; } if (surface_queue->impl && surface_queue->impl->enqueue) @@ -925,7 +1102,7 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; + return TBM_SURFACE_QUEUE_ERROR_EMPTY; } node->type = QUEUE_NODE_TYPE_ENQUEUE; @@ -935,6 +1112,8 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h _tbm_surf_queue_mutex_unlock(); + _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE); + _notify_emit(surface_queue, &surface_queue->acquirable_noti); return TBM_SURFACE_QUEUE_ERROR_NONE; @@ -944,10 +1123,12 @@ tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue, tbm_surface_h *surface) { - queue_node *node = NULL; + queue_node *node; _tbm_surf_queue_mutex_lock(); + *surface = NULL; + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL, @@ -955,28 +1136,31 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h pthread_mutex_lock(&surface_queue->lock); + if (_queue_is_empty(&surface_queue->free_queue)) { + if (surface_queue->impl && surface_queue->impl->need_attach) + surface_queue->impl->need_attach(surface_queue); + + if (!_tbm_surface_queue_is_valid(surface_queue)) { + TBM_LOG_E("surface_queue:%p is invalid", surface_queue); + pthread_mutex_unlock(&surface_queue->lock); + _tbm_surf_queue_mutex_unlock(); + return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; + } + } + if (surface_queue->impl && surface_queue->impl->dequeue) node = surface_queue->impl->dequeue(surface_queue); else node = _tbm_surface_queue_dequeue(surface_queue); - if (node == NULL) { - *surface = NULL; + if (node == NULL || node->surface == NULL) { + TBM_LOG_E("_queue_node_pop_front failed\n"); pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); return TBM_SURFACE_QUEUE_ERROR_EMPTY; } - if (node->surface == NULL) { - *surface = NULL; - TBM_LOG_E("_queue_node_pop_front failed\n"); - pthread_mutex_unlock(&surface_queue->lock); - - _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; - } - node->type = QUEUE_NODE_TYPE_DEQUEUE; *surface = node->surface; @@ -986,6 +1170,8 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h _tbm_surf_queue_mutex_unlock(); + _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE); + _notify_emit(surface_queue, &surface_queue->dequeue_noti); return TBM_SURFACE_QUEUE_ERROR_NONE; @@ -998,6 +1184,14 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait) TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0); + _tbm_surf_queue_mutex_unlock(); + + _notify_emit(surface_queue, &surface_queue->can_dequeue_noti); + + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0); + pthread_mutex_lock(&surface_queue->lock); TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); @@ -1007,52 +1201,47 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait) surface_queue->impl->need_attach(surface_queue); if (!_tbm_surface_queue_is_valid(surface_queue)) { - TBM_LOG_E("surface_queue:%p is invalid", surface_queue); - _tbm_surf_queue_mutex_unlock(); - return 0; + TBM_LOG_E("surface_queue:%p is invalid", surface_queue); + pthread_mutex_unlock(&surface_queue->lock); + _tbm_surf_queue_mutex_unlock(); + return 0; } } - if (_queue_is_empty(&surface_queue->free_queue)) { - if (wait && - _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE)) { - - _tbm_surf_queue_mutex_unlock(); - - pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock); - - _tbm_surf_queue_mutex_lock(); + if (!_queue_is_empty(&surface_queue->free_queue)) { + pthread_mutex_unlock(&surface_queue->lock); + _tbm_surf_queue_mutex_unlock(); + return 1; + } - if (!_tbm_surface_queue_is_valid(surface_queue)) { - TBM_LOG_E("surface_queue:%p is invalid", surface_queue); - _tbm_surf_queue_mutex_unlock(); - return 0; - } + if (wait && _tbm_surface_queue_get_node_count(surface_queue, + QUEUE_NODE_TYPE_ACQUIRE)) { + _tbm_surf_queue_mutex_unlock(); + pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock); + _tbm_surf_queue_mutex_lock(); + if (!_tbm_surface_queue_is_valid(surface_queue)) { + TBM_LOG_E("surface_queue:%p is invalid", surface_queue); pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - return 1; + return 0; } pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - return 0; + return 1; } pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - - return 1; + return 0; } tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - queue_node *node = NULL; + queue_node *node; int queue_type; _tbm_surf_queue_mutex_lock(); @@ -1068,16 +1257,19 @@ tbm_surface_queue_release(tbm_surface_queue_h node = _queue_get_node(surface_queue, 0, surface, &queue_type); if (node == NULL || queue_type != NODE_LIST) { - TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", + TBM_LOG_E("tbm_surface_queue_release::Surface is existed in free_queue or dirty_queue node:%p, type:%d\n", node, queue_type); pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; + + if (!node) + return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE; + else + return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST; } if (surface_queue->queue_size < surface_queue->num_attached) { - TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface); if (surface_queue->impl && surface_queue->impl->need_detach) @@ -1099,8 +1291,9 @@ tbm_surface_queue_release(tbm_surface_queue_h if (_queue_is_empty(&surface_queue->free_queue)) { pthread_mutex_unlock(&surface_queue->lock); + TBM_LOG_E("surface_queue->free_queue is empty.\n"); _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_NONE; + return TBM_SURFACE_QUEUE_ERROR_EMPTY; } node->type = QUEUE_NODE_TYPE_RELEASE; @@ -1110,6 +1303,8 @@ tbm_surface_queue_release(tbm_surface_queue_h _tbm_surf_queue_mutex_unlock(); + _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE); + _notify_emit(surface_queue, &surface_queue->dequeuable_noti); return TBM_SURFACE_QUEUE_ERROR_NONE; @@ -1119,10 +1314,12 @@ tbm_surface_queue_error_e tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue, tbm_surface_h *surface) { - queue_node *node = NULL; + queue_node *node; _tbm_surf_queue_mutex_lock(); + *surface = NULL; + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(surface != NULL, @@ -1135,23 +1332,14 @@ tbm_surface_queue_acquire(tbm_surface_queue_h else node = _tbm_surface_queue_acquire(surface_queue); - if (node == NULL) { - *surface = NULL; + if (node == NULL || node->surface == NULL) { + TBM_LOG_E("_queue_node_pop_front failed\n"); pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); return TBM_SURFACE_QUEUE_ERROR_EMPTY; } - if (node->surface == NULL) { - *surface = NULL; - TBM_LOG_E("_queue_node_pop_front failed\n"); - pthread_mutex_unlock(&surface_queue->lock); - - _tbm_surf_queue_mutex_unlock(); - return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; - } - node->type = QUEUE_NODE_TYPE_ACQUIRE; *surface = node->surface; @@ -1165,6 +1353,8 @@ tbm_surface_queue_acquire(tbm_surface_queue_h if (b_dump_queue) tbm_surface_internal_dump_buffer(*surface, "acquire"); + _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE); + return TBM_SURFACE_QUEUE_ERROR_NONE; } @@ -1179,45 +1369,39 @@ tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait) TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); - if (_queue_is_empty(&surface_queue->dirty_queue)) { - if (wait && - _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) { - - _tbm_surf_queue_mutex_unlock(); - - pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock); - - _tbm_surf_queue_mutex_lock(); + if (!_queue_is_empty(&surface_queue->dirty_queue)) { + pthread_mutex_unlock(&surface_queue->lock); + _tbm_surf_queue_mutex_unlock(); + return 1; + } - if (!_tbm_surface_queue_is_valid(surface_queue)) { - TBM_LOG_E("surface_queue:%p is invalid", surface_queue); - _tbm_surf_queue_mutex_unlock(); - return 0; - } + if (wait && _tbm_surface_queue_get_node_count(surface_queue, + QUEUE_NODE_TYPE_DEQUEUE)) { + _tbm_surf_queue_mutex_unlock(); + pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock); + _tbm_surf_queue_mutex_lock(); + if (!_tbm_surface_queue_is_valid(surface_queue)) { + TBM_LOG_E("surface_queue:%p is invalid", surface_queue); pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - return 1; + return 0; } pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - return 0; + return 1; } pthread_mutex_unlock(&surface_queue->lock); - _tbm_surf_queue_mutex_unlock(); - - return 1; + return 0; } void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue) { - queue_node *node = NULL, *tmp = NULL; + queue_node *node = NULL, *tmp; _tbm_surf_queue_mutex_lock(); @@ -1225,9 +1409,10 @@ tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue) TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_DEL(&surface_queue->item_link); + + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) _queue_delete_node(surface_queue, node); - } if (surface_queue->impl && surface_queue->impl->destroy) surface_queue->impl->destroy(surface_queue); @@ -1235,16 +1420,16 @@ tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue) _notify_emit(surface_queue, &surface_queue->destory_noti); _notify_remove_all(&surface_queue->destory_noti); - _notify_remove_all(&surface_queue->acquirable_noti); _notify_remove_all(&surface_queue->dequeuable_noti); + _notify_remove_all(&surface_queue->dequeue_noti); + _notify_remove_all(&surface_queue->can_dequeue_noti); + _notify_remove_all(&surface_queue->acquirable_noti); _notify_remove_all(&surface_queue->reset_noti); + _trace_remove_all(&surface_queue->trace_noti); pthread_mutex_destroy(&surface_queue->lock); - LIST_DEL(&surface_queue->item_link); - free(surface_queue); - surface_queue = NULL; if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) _deinit_tbm_surf_queue_bufmgr(); @@ -1256,7 +1441,7 @@ tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_queue, int width, int height, int format) { - queue_node *node = NULL, *tmp = NULL; + queue_node *node = NULL, *tmp; _tbm_surf_queue_mutex_lock(); @@ -1266,7 +1451,7 @@ tbm_surface_queue_reset(tbm_surface_queue_h TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); if (width == surface_queue->width && height == surface_queue->height && - format == surface_queue->format) { + format == surface_queue->format) { _tbm_surf_queue_mutex_unlock(); return TBM_SURFACE_QUEUE_ERROR_NONE; } @@ -1278,9 +1463,8 @@ tbm_surface_queue_reset(tbm_surface_queue_h surface_queue->format = format; /* Destory surface and Push to free_queue */ - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) _queue_delete_node(surface_queue, node); - } /* Reset queue */ _queue_init(&surface_queue->free_queue); @@ -1303,11 +1487,25 @@ tbm_surface_queue_reset(tbm_surface_queue_h } tbm_surface_queue_error_e +tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue) +{ + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + _tbm_surf_queue_mutex_unlock(); + + _notify_emit(surface_queue, &surface_queue->reset_noti); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +tbm_surface_queue_error_e tbm_surface_queue_set_size(tbm_surface_queue_h surface_queue, int queue_size, int flush) { - queue_node *node = NULL, *tmp = NULL; - int need_del; + queue_node *node = NULL, *tmp; _tbm_surf_queue_mutex_lock(); @@ -1327,9 +1525,8 @@ tbm_surface_queue_set_size(tbm_surface_queue_h if (flush) { /* Destory surface and Push to free_queue */ - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) _queue_delete_node(surface_queue, node); - } /* Reset queue */ _queue_init(&surface_queue->free_queue); @@ -1350,15 +1547,11 @@ tbm_surface_queue_set_size(tbm_surface_queue_h _notify_emit(surface_queue, &surface_queue->reset_noti); return TBM_SURFACE_QUEUE_ERROR_NONE; - } - else { - + } else { if (surface_queue->queue_size > queue_size) { - - need_del = surface_queue->queue_size - queue_size; + int need_del = surface_queue->queue_size - queue_size; LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) { - TBM_QUEUE_TRACE("deatch tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface); if (surface_queue->impl && surface_queue->impl->need_detach) @@ -1383,9 +1576,45 @@ tbm_surface_queue_set_size(tbm_surface_queue_h } tbm_surface_queue_error_e +tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue) +{ + queue_node *node = NULL; + + _tbm_surf_queue_mutex_lock(); + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue); + + if (surface_queue->num_attached == 0) { + _tbm_surf_queue_mutex_unlock(); + return TBM_SURFACE_QUEUE_ERROR_NONE; + } + + pthread_mutex_lock(&surface_queue->lock); + + /* Destory surface in free_queue */ + while ((node = _queue_node_pop_front(&surface_queue->free_queue))) { + if (surface_queue->impl && surface_queue->impl->need_detach) + surface_queue->impl->need_detach(surface_queue, node); + else + _tbm_surface_queue_detach(surface_queue, node->surface); + } + + /* Reset queue */ + _queue_init(&surface_queue->free_queue); + + pthread_mutex_unlock(&surface_queue->lock); + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +tbm_surface_queue_error_e tbm_surface_queue_flush(tbm_surface_queue_h surface_queue) { - queue_node *node = NULL, *tmp = NULL; + queue_node *node = NULL, *tmp; _tbm_surf_queue_mutex_lock(); @@ -1402,9 +1631,8 @@ tbm_surface_queue_flush(tbm_surface_queue_h surface_queue) pthread_mutex_lock(&surface_queue->lock); /* Destory surface and Push to free_queue */ - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) _queue_delete_node(surface_queue, node); - } /* Reset queue */ _queue_init(&surface_queue->free_queue); @@ -1431,10 +1659,11 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue, tbm_surface_h *surfaces, int *num) { queue_node *node = NULL; - queue_node *tmp = NULL; _tbm_surf_queue_mutex_lock(); + *num = 0; + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL, @@ -1442,8 +1671,7 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue, pthread_mutex_lock(&surface_queue->lock); - *num = 0; - LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + LIST_FOR_EACH_ENTRY(node, &surface_queue->list, link) { if (surfaces) surfaces[*num] = node->surface; @@ -1457,6 +1685,46 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue, return TBM_SURFACE_QUEUE_ERROR_NONE; } +tbm_surface_queue_error_e +tbm_surface_queue_get_trace_surface_num( + tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num) +{ + _tbm_surf_queue_mutex_lock(); + + *num = 0; + + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), + TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL, + TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER); + + pthread_mutex_lock(&surface_queue->lock); + + switch (trace) { + case TBM_SURFACE_QUEUE_TRACE_NONE: + *num = 0; + break; + case TBM_SURFACE_QUEUE_TRACE_DEQUEUE: + *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE); + break; + case TBM_SURFACE_QUEUE_TRACE_ENQUEUE: + *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE); + break; + case TBM_SURFACE_QUEUE_TRACE_ACQUIRE: + *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE); + break; + case TBM_SURFACE_QUEUE_TRACE_RELEASE: + *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE); + break; + } + + pthread_mutex_unlock(&surface_queue->lock); + + _tbm_surf_queue_mutex_unlock(); + + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + typedef struct { int flags; } tbm_queue_default; @@ -1470,17 +1738,20 @@ __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue) static void __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue) { - tbm_queue_default *data = surface_queue->impl_data; + tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data; tbm_surface_h surface; if (surface_queue->queue_size == surface_queue->num_attached) return; if (surface_queue->alloc_cb) { + pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data); _tbm_surf_queue_mutex_lock(); + pthread_mutex_lock(&surface_queue->lock); + /* silent return */ if (!surface) return; @@ -1498,7 +1769,7 @@ __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue) } static const tbm_surface_queue_interface tbm_queue_default_impl = { - NULL, /*__tbm_queue_default_init*/ + NULL, /*__tbm_queue_default_init*/ NULL, /*__tbm_queue_default_reset*/ __tbm_queue_default_destroy, __tbm_queue_default_need_attach, @@ -1529,6 +1800,7 @@ tbm_surface_queue_create(int queue_size, int width, tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default)); if (data == NULL) { + TBM_LOG_E("cannot allocate the tbm_queue_default.\n"); free(surface_queue); _tbm_surf_queue_mutex_unlock(); return NULL; @@ -1553,7 +1825,7 @@ typedef struct { static void __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue) { - tbm_queue_sequence *data = surface_queue->impl_data; + tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data; _queue_init(&data->dequeue_list); } @@ -1561,7 +1833,7 @@ __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue) static void __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue) { - tbm_queue_sequence *data = surface_queue->impl_data; + tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data; _queue_init(&data->dequeue_list); } @@ -1575,17 +1847,20 @@ __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue) static void __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue) { - tbm_queue_sequence *data = surface_queue->impl_data; + tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data; tbm_surface_h surface; if (surface_queue->queue_size == surface_queue->num_attached) return; if (surface_queue->alloc_cb) { + pthread_mutex_unlock(&surface_queue->lock); _tbm_surf_queue_mutex_unlock(); surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data); _tbm_surf_queue_mutex_lock(); + pthread_mutex_lock(&surface_queue->lock); + /* silent return */ if (!surface) return; @@ -1606,9 +1881,8 @@ static void __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue, queue_node *node) { - tbm_queue_sequence *data = surface_queue->impl_data; - queue_node *next = NULL; - queue_node *tmp = NULL; + tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data; + queue_node *next = NULL, *tmp; node->priv_flags = 0; @@ -1624,8 +1898,8 @@ static queue_node * __tbm_queue_sequence_dequeue(tbm_surface_queue_h surface_queue) { - tbm_queue_sequence *data = surface_queue->impl_data; - queue_node *node = NULL; + tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data; + queue_node *node; node = _tbm_surface_queue_dequeue(surface_queue); if (node) { @@ -1668,6 +1942,7 @@ tbm_surface_queue_sequence_create(int queue_size, int width, tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1, sizeof(tbm_queue_sequence)); if (data == NULL) { + TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n"); free(surface_queue); _tbm_surf_queue_mutex_unlock(); return NULL;