From d0dffc1e9f82cacb0a8908a684cb07ea737c06be Mon Sep 17 00:00:00 2001 From: Sangjin Lee Date: Tue, 2 Feb 2016 11:11:00 +0900 Subject: [PATCH] tbm_surface_queue: add sequence queue Change-Id: I183800b929324f5b69f4f88943e2cf348385ba0a --- src/tbm_surface_queue.c | 269 +++++++++++++++++++++++++++++++++++------------- src/tbm_surface_queue.h | 10 +- 2 files changed, 201 insertions(+), 78 deletions(-) diff --git a/src/tbm_surface_queue.c b/src/tbm_surface_queue.c index daa5626..8f92e83 100644 --- a/src/tbm_surface_queue.c +++ b/src/tbm_surface_queue.c @@ -60,18 +60,20 @@ typedef struct { struct list_head item_link; struct list_head link; + + unsigned int priv_flags; /*for each queue*/ } queue_node; typedef struct _tbm_surface_queue_interface { void (*init)(tbm_surface_queue_h queue); - void (*reset)(tbm_surface_queue_h queue); + void (*reset)(tbm_surface_queue_h queue); void (*destroy)(tbm_surface_queue_h queue); void (*need_attach)(tbm_surface_queue_h queue); - void (*enqueue)(tbm_surface_queue_h queue, tbm_surface_h surface); - void (*release)(tbm_surface_queue_h queue, tbm_surface_h surface); - void (*dequeue)(tbm_surface_queue_h queue); - void (*acquire)(tbm_surface_queue_h queue); + void (*enqueue)(tbm_surface_queue_h queue, queue_node* node); + void (*release)(tbm_surface_queue_h queue, queue_node* node); + queue_node* (*dequeue)(tbm_surface_queue_h queue); + queue_node* (*acquire)(tbm_surface_queue_h queue); }tbm_surface_queue_interface; struct _tbm_surface_queue { @@ -155,6 +157,14 @@ static queue_node *_queue_node_pop_front(queue * queue) return node; } +static queue_node *_queue_node_pop(queue * queue, queue_node* node) +{ + LIST_DEL(&node->item_link); + queue->count--; + + return node; +} + static queue_node* _queue_get_node(tbm_surface_queue_h surface_queue, int type, tbm_surface_h surface, int *out_type) { queue_node *node = NULL; @@ -233,30 +243,47 @@ void _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, tbm_surface_h _queue_node_delete(node); } -void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface, int push_back) +void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, queue_node* node, int push_back) { - queue_node *node = NULL; - int queue_type; - - node = _queue_get_node(surface_queue, 0, surface, &queue_type); - TBM_RETURN_IF_FAIL(node != NULL); - TBM_RETURN_IF_FAIL(queue_type == NODE_LIST); - if (push_back) _queue_node_push_back(&surface_queue->dirty_queue, node); else _queue_node_push_front(&surface_queue->dirty_queue, node); } -void _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface, int push_back) +queue_node* _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue) { queue_node *node = NULL; - int queue_type; - node = _queue_get_node(surface_queue, 0, surface, &queue_type); - TBM_RETURN_IF_FAIL(node != NULL); - TBM_RETURN_IF_FAIL(queue_type == NODE_LIST); + 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; + } + } + + node = _queue_node_pop_front(&surface_queue->free_queue); + + return node; +} + +queue_node* _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue) +{ + queue_node *node = NULL; + + if (_queue_is_empty(&surface_queue->dirty_queue)) { + return NULL; + } + + node = _queue_node_pop_front(&surface_queue->dirty_queue); + + return node; +} + +void _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, queue_node* node, int push_back) +{ if (push_back) _queue_node_push_back(&surface_queue->free_queue, node); else @@ -383,14 +410,19 @@ tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_ } if (surface_queue->impl && surface_queue->impl->enqueue) - surface_queue->impl->enqueue(surface_queue, surface); + surface_queue->impl->enqueue(surface_queue, node); else - _queue_node_push_back(&surface_queue->dirty_queue, node); + _tbm_surface_queue_enqueue(surface_queue, node, 1); + + if (_queue_is_empty(&surface_queue->dirty_queue)) { + pthread_mutex_unlock(&surface_queue->lock); + return TBM_SURFACE_QUEUE_ERROR_NONE; + } pthread_mutex_unlock(&surface_queue->lock); pthread_cond_signal(&surface_queue->dirty_cond); - if (!_queue_is_empty(&surface_queue->dirty_queue) && surface_queue->acquirable_cb) + if (surface_queue->acquirable_cb) surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data); return TBM_SURFACE_QUEUE_ERROR_NONE; @@ -406,21 +438,14 @@ tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_ pthread_mutex_lock(&surface_queue->lock); if (surface_queue->impl && surface_queue->impl->dequeue) - surface_queue->impl->dequeue(surface_queue); - - 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)) { - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_EMPTY; - } - } + node = surface_queue->impl->dequeue(surface_queue); + else + node = _tbm_surface_queue_dequeue(surface_queue); - node = _queue_node_pop_front(&surface_queue->free_queue); if (node == NULL || node->surface == NULL) { TBM_LOG("_queue_node_pop_front is failed\n"); + + *surface = NULL; pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; } @@ -478,14 +503,19 @@ tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_ } if (surface_queue->impl && surface_queue->impl->release) - surface_queue->impl->release(surface_queue, surface); + surface_queue->impl->release(surface_queue, node); else - _queue_node_push_front(&surface_queue->free_queue, node); + _tbm_surface_queue_release(surface_queue, node, 1); + + if (_queue_is_empty(&surface_queue->free_queue)) { + pthread_mutex_unlock(&surface_queue->lock); + return TBM_SURFACE_QUEUE_ERROR_NONE; + } pthread_mutex_unlock(&surface_queue->lock); pthread_cond_signal(&surface_queue->free_cond); - if (!_queue_is_empty(&surface_queue->free_queue) && surface_queue->dequeuable_cb) + if (surface_queue->dequeuable_cb) surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data); return TBM_SURFACE_QUEUE_ERROR_NONE; @@ -496,21 +526,19 @@ tbm_surface_queue_error_e tbm_surface_queue_acquire(tbm_surface_queue_h surface_ queue_node *node = NULL; TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE); + TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE); pthread_mutex_lock(&surface_queue->lock); if (surface_queue->impl && surface_queue->impl->acquire) - surface_queue->impl->acquire(surface_queue); - - if (_queue_is_empty(&surface_queue->dirty_queue)) { - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_EMPTY; - } + node = surface_queue->impl->acquire(surface_queue); + else + node = _tbm_surface_queue_acquire(surface_queue); - node = _queue_node_pop_front(&surface_queue->dirty_queue); - if (node == NULL) { + if (node == NULL || node->surface == NULL) { TBM_LOG("_queue_node_pop_front failed\n"); + + *surface = NULL; pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; } @@ -579,7 +607,7 @@ tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_qu surface_queue->height = height; surface_queue->format = format; - /* Destory surface and Push to free_queue */ + /* Destory surface and Push to free_queue */ LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { _queue_node_delete(node); @@ -588,7 +616,7 @@ tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_qu /* Reset queue */ _queue_init(&surface_queue->free_queue); _queue_init(&surface_queue->dirty_queue); - LIST_INITHEAD(&surface_queue->list); + LIST_INITHEAD(&surface_queue->list); if (surface_queue->impl && surface_queue->impl->reset) surface_queue->impl->reset(surface_queue); @@ -611,12 +639,14 @@ typedef struct static void __tbm_queue_default_init(tbm_surface_queue_h surface_queue) { + tbm_queue_default* data = surface_queue->impl_data; + data->num_attached = 0; } static void __tbm_queue_default_reset(tbm_surface_queue_h surface_queue) { - tbm_queue_default* data = surface_queue->impl_data; - data->num_attached = 0; + tbm_queue_default* data = surface_queue->impl_data; + data->num_attached = 0; } static void __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue) @@ -642,41 +672,137 @@ static void __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue) data->num_attached++; } -static void __tbm_queue_default_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface) +static const tbm_surface_queue_interface tbm_queue_default_impl = +{ + __tbm_queue_default_init, + __tbm_queue_default_reset, + __tbm_queue_default_destroy, + __tbm_queue_default_need_attach, + NULL, /*__tbm_queue_default_enqueue*/ + NULL, /*__tbm_queue_default_release*/ + NULL, /*__tbm_queue_default_dequeue*/ + NULL, /*__tbm_queue_default_acquire*/ +}; + +tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags) +{ + TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL); + TBM_RETURN_VAL_IF_FAIL(width > 0, NULL); + TBM_RETURN_VAL_IF_FAIL(height > 0, NULL); + TBM_RETURN_VAL_IF_FAIL(format > 0, NULL); + + tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue)); + TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL); + + tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default)); + if (data == NULL) + { + free(surface_queue); + return NULL; + } + + data->queue_size = queue_size; + data->flags = flags; + _tbm_surface_queue_init(surface_queue, + width, height, format, + &tbm_queue_default_impl, data); + + return surface_queue; +} + +typedef struct +{ + int queue_size; + int num_attached; + int flags; + queue dequeue_list; + queue enqueue_list; +}tbm_queue_sequence; + +static void __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue) { - /* Push to back of dirty_queue */ - _tbm_surface_queue_enqueue(surface_queue, surface, 1); + tbm_queue_sequence* data = surface_queue->impl_data; + + data->num_attached = 0; + _queue_init(&data->dequeue_list); + _queue_init(&data->enqueue_list); } -static void __tbm_queue_default_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface) +static void __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue) { - /* Push to front of free_queue */ - _tbm_surface_queue_release(surface_queue, surface, 0); + tbm_queue_sequence* data = surface_queue->impl_data; + + data->num_attached = 0; + _queue_init(&data->dequeue_list); + _queue_init(&data->enqueue_list); } -static void __tbm_queue_default_dequeue(tbm_surface_queue_h surface_queue) +static void __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue) { - /*NOOP*/ + free(surface_queue->impl_data); } -static void __tbm_queue_default_acquire(tbm_surface_queue_h surface_queue) +static void __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue) { - /*NOOP*/ + tbm_queue_sequence* data = surface_queue->impl_data; + tbm_surface_h surface; + + if (data->queue_size == data->num_attached) + return; + + surface = tbm_surface_internal_create_with_flags(surface_queue->width, + surface_queue->height, + surface_queue->format, + data->flags); + TBM_RETURN_IF_FAIL(surface != NULL); + _tbm_surface_queue_attach(surface_queue, surface); + tbm_surface_internal_unref(surface); + data->num_attached++; } -static const tbm_surface_queue_interface tbm_queue_default_impl = +static void __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue, queue_node* node) { - __tbm_queue_default_init, - __tbm_queue_default_reset, - __tbm_queue_default_destroy, - __tbm_queue_default_need_attach, - __tbm_queue_default_enqueue, - __tbm_queue_default_release, - __tbm_queue_default_dequeue, - __tbm_queue_default_acquire + tbm_queue_sequence* data = surface_queue->impl_data; + queue_node *next = NULL; + queue_node *tmp = NULL; + + node->priv_flags = 0; + + LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) { + if (next->priv_flags) break; + _queue_node_pop(&data->dequeue_list, next); + _tbm_surface_queue_enqueue(surface_queue, next, 1); + } +} + +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; + + node = _tbm_surface_queue_dequeue(surface_queue); + if (node) + { + _queue_node_push_back(&data->dequeue_list, node); + node->priv_flags = 1; + } + + return node; +} + +static const tbm_surface_queue_interface tbm_queue_sequence_impl = +{ + __tbm_queue_sequence_init, + __tbm_queue_sequence_reset, + __tbm_queue_sequence_destroy, + __tbm_queue_sequence_need_attach, + __tbm_queue_sequence_enqueue, + NULL, /*__tbm_queue_sequence_release*/ + __tbm_queue_sequence_dequeue, + NULL, /*__tbm_queue_sequence_acquire*/ }; -tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags) +tbm_surface_queue_h tbm_surface_queue_sequence_create(int queue_size, int width, int height, int format, int flags) { TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL); TBM_RETURN_VAL_IF_FAIL(width > 0, NULL); @@ -686,7 +812,7 @@ tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int heig tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue)); TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL); - tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default)); + tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1, sizeof(tbm_queue_sequence)); if (data == NULL) { free(surface_queue); @@ -697,8 +823,7 @@ tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int heig data->flags = flags; _tbm_surface_queue_init(surface_queue, width, height, format, - &tbm_queue_default_impl, data); + &tbm_queue_sequence_impl, data); return surface_queue; } - diff --git a/src/tbm_surface_queue.h b/src/tbm_surface_queue.h index 67f576a..c71992a 100644 --- a/src/tbm_surface_queue.h +++ b/src/tbm_surface_queue.h @@ -63,8 +63,6 @@ int tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait); int tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait); -tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags); - 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); 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); @@ -72,10 +70,6 @@ tbm_surface_queue_error_e tbm_surface_queue_set_dequeuable_cb(tbm_surface_queue_ 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); void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue); -#if 0 - -int tbm_surface_queue_get_queue_size(tbm_surface_queue_h surface_queue); -#endif int tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue); @@ -87,6 +81,10 @@ tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_qu 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); +/*The functions of queue factory*/ +tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags); +tbm_surface_queue_h tbm_surface_queue_sequence_create(int queue_size, int width, int height, int format, int flags); + #ifdef __cplusplus } #endif -- 2.7.4