From: Sangjin Lee Date: Mon, 1 Feb 2016 10:24:17 +0000 (+0900) Subject: Refactoring tbm_surface_queue X-Git-Tag: accepted/tizen/ivi/20160218.024517~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=309b3e23763a7ee9b3878063ed3610a0f15152ce;p=platform%2Fcore%2Fuifw%2Flibtbm.git Refactoring tbm_surface_queue Change-Id: I2b01d213a3eed54a608086b0427a63336cc5df6c --- diff --git a/src/tbm_surface_queue.c b/src/tbm_surface_queue.c index 5757a33..daa5626 100644 --- a/src/tbm_surface_queue.c +++ b/src/tbm_surface_queue.c @@ -32,9 +32,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tbm_bufmgr_int.h" #include "list.h" +#define FREE_QUEUE 1 +#define DUTY_QUEUE 2 +#define NODE_LIST 4 + +#define DEBUG 0 + +#if DEBUG +#define TBM_TRACE() TBM_LOG("[TRACE] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue) +#define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue) +#define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue) +#else +#define TBM_TRACE() +#define TBM_LOCK() +#define TBM_UNLOCK() +#endif + typedef struct { struct list_head head; - struct list_head tail; int count; @@ -44,18 +59,29 @@ typedef struct { tbm_surface_h surface; struct list_head item_link; + struct list_head link; } queue_node; +typedef struct _tbm_surface_queue_interface { + void (*init)(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); +}tbm_surface_queue_interface; + struct _tbm_surface_queue { int width; int height; int format; - int size; - int flags; queue free_queue; - queue duty_queue; - queue_node **node_list; + queue dirty_queue; + struct list_head list; tbm_surface_queue_notify_cb destroy_cb; void *destroy_cb_data; @@ -71,7 +97,10 @@ struct _tbm_surface_queue { pthread_mutex_t lock; pthread_cond_t free_cond; - pthread_cond_t duty_cond; + pthread_cond_t dirty_cond; + + const tbm_surface_queue_interface *impl; + void *impl_data; }; static queue_node *_queue_node_create(void) @@ -86,7 +115,9 @@ static void _queue_node_delete(queue_node * node) { if (node->surface) tbm_surface_destroy(node->surface); + LIST_DEL(&node->item_link); + LIST_DEL(&node->link); free(node); } @@ -124,19 +155,50 @@ static queue_node *_queue_node_pop_front(queue * queue) return node; } -static int _queue_node_exist_in_queue(queue * queue, queue_node * node) +static queue_node* _queue_get_node(tbm_surface_queue_h surface_queue, int type, tbm_surface_h surface, int *out_type) { - queue_node *search_node = NULL; - queue_node *temp = NULL; + queue_node *node = NULL; + queue_node *tmp = NULL; + + if (type == 0) + type = FREE_QUEUE | DUTY_QUEUE | NODE_LIST; + if (out_type) + *out_type = 0; + + if (type & FREE_QUEUE) + { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) { + if (node->surface == surface) + { + if (out_type) *out_type = FREE_QUEUE; + return node; + } + } + } - if (!_queue_is_empty(queue)) { - LIST_FOR_EACH_ENTRY_SAFE(search_node, temp, &queue->head, item_link) { - if (search_node == node) - return 1; + if (type & DUTY_QUEUE) + { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head, item_link) { + if (node->surface == surface) + { + if (out_type) *out_type = DUTY_QUEUE; + return node; + } } } - return 0; + if (type & NODE_LIST) + { + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + if (node->surface == surface) + { + if (out_type) *out_type = NODE_LIST; + return node; + } + } + } + + return NULL; } static void _queue_init(queue * queue) @@ -147,138 +209,218 @@ static void _queue_init(queue * queue) queue->count = 0; } -tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface) +void _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE); + queue_node *node = NULL; - int i; + node = _queue_node_create(); + TBM_RETURN_IF_FAIL(node != NULL); - pthread_mutex_lock(&surface_queue->lock); + tbm_surface_internal_ref(surface); + node->surface = surface; - for (i = 0; i < surface_queue->size; i++) { - if (surface_queue->node_list[i]->surface == surface) - break; - } + LIST_ADDTAIL(&node->link, &surface_queue->list); + _queue_node_push_back(&surface_queue->free_queue, node); +} - if (i == surface_queue->size) { - TBM_LOG("Can't find the surface in queue\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; - } +void _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, tbm_surface_h surface) +{ + queue_node *node = NULL; + int queue_type; - if (_queue_node_exist_in_queue(&surface_queue->duty_queue, surface_queue->node_list[i])) { - TBM_LOG("Surface exist in queue\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; - } + node = _queue_get_node(surface_queue, 0, surface, &queue_type); + if (node) + _queue_node_delete(node); +} + +void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface, 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 *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->free_queue, node); + else + _queue_node_push_front(&surface_queue->free_queue, node); +} + +void _tbm_surface_queue_init(tbm_surface_queue_h surface_queue, + int width, int height, int format, + const tbm_surface_queue_interface* impl, void *data) +{ + TBM_RETURN_IF_FAIL(surface_queue != NULL); + TBM_RETURN_IF_FAIL(impl != NULL); + + memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue)); + + pthread_mutex_init(&surface_queue->lock, NULL); + pthread_cond_init(&surface_queue->free_cond, NULL); + pthread_cond_init(&surface_queue->dirty_cond, NULL); + + surface_queue->width = width; + surface_queue->height = height; + surface_queue->format = format; + surface_queue->impl = impl; + surface_queue->impl_data = data; + + _queue_init(&surface_queue->free_queue); + _queue_init(&surface_queue->dirty_queue); + LIST_INITHEAD(&surface_queue->list); + + if (surface_queue->impl && surface_queue->impl->init) + surface_queue->impl->init(surface_queue); +} + +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_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); - _queue_node_push_back(&surface_queue->duty_queue, surface_queue->node_list[i]); + surface_queue->destroy_cb = destroy_cb; + surface_queue->destroy_cb_data = data; pthread_mutex_unlock(&surface_queue->lock); - pthread_cond_signal(&surface_queue->duty_cond); - if (surface_queue->acquirable_cb) - surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data); + return TBM_SURFACE_QUEUE_ERROR_NONE; +} + +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) +{ + TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + surface_queue->dequeuable_cb = dequeuable_cb; + surface_queue->dequeuable_cb_data = data; + + pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_NONE; } -tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue, tbm_surface_h * surface) +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) { TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - TBM_RETURN_VAL_IF_FAIL(surface_queue->free_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY); pthread_mutex_lock(&surface_queue->lock); - if (_queue_is_empty(&surface_queue->free_queue)) { - TBM_LOG("Surface queue is empty\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_EMPTY; - } + surface_queue->acquirable_cb = acquirable_cb; + surface_queue->acquirable_cb_data = data; - queue_node *node = NULL; + pthread_mutex_unlock(&surface_queue->lock); - node = _queue_node_pop_front(&surface_queue->free_queue); - if (node == NULL) { - TBM_LOG("_queue_node_pop_front is failed\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; - } + return TBM_SURFACE_QUEUE_ERROR_NONE; +} - if (!node->surface) { - tbm_surface_h surface = tbm_surface_internal_create_with_flags(surface_queue->width, - surface_queue->height, - surface_queue->format, - surface_queue->flags); - if (surface == NULL) { - TBM_LOG("tbm surface create failed"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_SURFACE_ALLOC_FAILED; - } - node->surface = surface; - } +int tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue) +{ + TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0); - *surface = node->surface; + return surface_queue->width; +} + +int tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue) +{ + return surface_queue->height; +} + +int tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue) +{ + return surface_queue->format; +} + +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) +{ + TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + + pthread_mutex_lock(&surface_queue->lock); + + surface_queue->reset_cb = reset_cb; + surface_queue->reset_cb_data = data; pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_NONE; } -tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface) + +tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { + queue_node *node = NULL; + int queue_type; + 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); pthread_mutex_lock(&surface_queue->lock); - int i; - for (i = 0; i < surface_queue->size; i++) { - if (surface_queue->node_list[i]->surface == surface) - break; - } - if (i == surface_queue->size) { - TBM_LOG("Can't find the surface in queue\n"); + node = _queue_get_node(surface_queue, 0, surface, &queue_type); + if (node == NULL || queue_type != NODE_LIST) + { + TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type); pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; } - if (_queue_node_exist_in_queue(&surface_queue->free_queue, surface_queue->node_list[i])) { - TBM_LOG("Surface exist in queue\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; - } - - _queue_node_push_front(&surface_queue->free_queue, surface_queue->node_list[i]); + if (surface_queue->impl && surface_queue->impl->enqueue) + surface_queue->impl->enqueue(surface_queue, surface); + else + _queue_node_push_back(&surface_queue->dirty_queue, node); pthread_mutex_unlock(&surface_queue->lock); - pthread_cond_signal(&surface_queue->free_cond); + pthread_cond_signal(&surface_queue->dirty_cond); - if (surface_queue->dequeuable_cb) - surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data); + if (!_queue_is_empty(&surface_queue->dirty_queue) && surface_queue->acquirable_cb) + surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data); return TBM_SURFACE_QUEUE_ERROR_NONE; } -tbm_surface_queue_error_e tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue, tbm_surface_h * surface) +tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue, tbm_surface_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_queue->duty_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY); + TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE); pthread_mutex_lock(&surface_queue->lock); - if (_queue_is_empty(&surface_queue->duty_queue)) { - TBM_LOG("Surface queue is empty\n"); - pthread_mutex_unlock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_EMPTY; - } + if (surface_queue->impl && surface_queue->impl->dequeue) + surface_queue->impl->dequeue(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); - node = _queue_node_pop_front(&surface_queue->duty_queue); - if (node == NULL) { - TBM_LOG("_queue_node_pop_front failed\n"); + if (_queue_is_empty(&surface_queue->free_queue)) { + pthread_mutex_unlock(&surface_queue->lock); + return TBM_SURFACE_QUEUE_ERROR_EMPTY; + } + } + + node = _queue_node_pop_front(&surface_queue->free_queue); + if (node == NULL || node->surface == NULL) { + TBM_LOG("_queue_node_pop_front is failed\n"); pthread_mutex_unlock(&surface_queue->lock); return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; } @@ -297,6 +439,11 @@ int tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait) 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 (_queue_is_empty(&surface_queue->free_queue)) { if (wait) { pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock); pthread_mutex_unlock(&surface_queue->lock); @@ -308,219 +455,250 @@ int tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait) } pthread_mutex_unlock(&surface_queue->lock); + return 1; } -int tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait) +tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0); + queue_node *node = NULL; + int queue_type; - pthread_mutex_lock(&surface_queue->lock); + 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); - if (_queue_is_empty(&surface_queue->duty_queue)) { - if (wait) { - pthread_cond_wait(&surface_queue->duty_cond, &surface_queue->lock); - pthread_mutex_unlock(&surface_queue->lock); - return 1; - } + pthread_mutex_lock(&surface_queue->lock); + node = _queue_get_node(surface_queue, 0, surface, &queue_type); + if (node == NULL || queue_type != NODE_LIST) + { + TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type); pthread_mutex_unlock(&surface_queue->lock); - return 0; + return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE; } + if (surface_queue->impl && surface_queue->impl->release) + surface_queue->impl->release(surface_queue, surface); + else + _queue_node_push_front(&surface_queue->free_queue, node); + pthread_mutex_unlock(&surface_queue->lock); + pthread_cond_signal(&surface_queue->free_cond); - return 1; + if (!_queue_is_empty(&surface_queue->free_queue) && surface_queue->dequeuable_cb) + surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data); + + return TBM_SURFACE_QUEUE_ERROR_NONE; } -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_acquire(tbm_surface_queue_h surface_queue, tbm_surface_h * surface) { - 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); + queue_node *node = NULL; - int i, j; - 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_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); - pthread_mutex_init(&surface_queue->lock, NULL); - pthread_cond_init(&surface_queue->free_cond, NULL); - pthread_cond_init(&surface_queue->duty_cond, NULL); + pthread_mutex_lock(&surface_queue->lock); - surface_queue->width = width; - surface_queue->height = height; - surface_queue->format = format; - surface_queue->flags = flags; - surface_queue->size = queue_size; - surface_queue->node_list = (queue_node **) calloc(queue_size, sizeof(queue_node *)); - if (!surface_queue->node_list) { - TBM_LOG("surface node list alloc failed"); - pthread_mutex_destroy(&surface_queue->lock); - free(surface_queue); - return NULL; + 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; } - _queue_init(&surface_queue->free_queue); - _queue_init(&surface_queue->duty_queue); + node = _queue_node_pop_front(&surface_queue->dirty_queue); + if (node == NULL) { + TBM_LOG("_queue_node_pop_front failed\n"); + pthread_mutex_unlock(&surface_queue->lock); + return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE; + } - for (i = 0; i < queue_size; i++) { - queue_node *node = _queue_node_create(); - if (node == NULL) { - TBM_LOG("surface node create failed"); - goto fail; - } + *surface = node->surface; - surface_queue->node_list[i] = node; - _queue_node_push_back(&surface_queue->free_queue, node); - } + pthread_mutex_unlock(&surface_queue->lock); - return surface_queue; + return TBM_SURFACE_QUEUE_ERROR_NONE; +} - fail: - for (j = 0; j < i; j++) - _queue_node_delete(surface_queue->node_list[j]); +int tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait) +{ + TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0); - free(surface_queue->node_list); - pthread_mutex_destroy(&surface_queue->lock); - free(surface_queue); + pthread_mutex_lock(&surface_queue->lock); - return NULL; + if (_queue_is_empty(&surface_queue->dirty_queue)) { + if (wait) { + pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock); + pthread_mutex_unlock(&surface_queue->lock); + return 1; + } + + pthread_mutex_unlock(&surface_queue->lock); + return 0; + } + + pthread_mutex_unlock(&surface_queue->lock); + + return 1; } void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue) { + queue_node *node = NULL, *tmp = NULL; + TBM_RETURN_IF_FAIL(surface_queue != NULL); if (surface_queue->destroy_cb) surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data); - int i; + if (surface_queue->impl && surface_queue->impl->destroy) + surface_queue->impl->destroy(surface_queue); - for (i = 0; i < surface_queue->size; i++) - _queue_node_delete(surface_queue->node_list[i]); + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) { + _queue_node_delete(node); + } - free(surface_queue->node_list); pthread_mutex_destroy(&surface_queue->lock); free(surface_queue); } -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_reset(tbm_surface_queue_h surface_queue, int width, int height, int format) { TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - pthread_mutex_lock(&surface_queue->lock); + queue_node *node = NULL, *tmp = NULL; - surface_queue->destroy_cb = destroy_cb; - surface_queue->destroy_cb_data = data; + if (width == surface_queue->width && height == surface_queue->height && format == surface_queue->format) + return TBM_SURFACE_QUEUE_ERROR_NONE; - pthread_mutex_unlock(&surface_queue->lock); + pthread_mutex_lock(&surface_queue->lock); - return TBM_SURFACE_QUEUE_ERROR_NONE; -} + surface_queue->width = width; + surface_queue->height = height; + surface_queue->format = format; -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) -{ - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); + /* Destory surface and Push to free_queue */ + LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) + { + _queue_node_delete(node); + } - pthread_mutex_lock(&surface_queue->lock); + /* Reset queue */ + _queue_init(&surface_queue->free_queue); + _queue_init(&surface_queue->dirty_queue); + LIST_INITHEAD(&surface_queue->list); - surface_queue->dequeuable_cb = dequeuable_cb; - surface_queue->dequeuable_cb_data = data; + if (surface_queue->impl && surface_queue->impl->reset) + surface_queue->impl->reset(surface_queue); pthread_mutex_unlock(&surface_queue->lock); + pthread_cond_signal(&surface_queue->free_cond); + + if (surface_queue->reset_cb) + surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data); return TBM_SURFACE_QUEUE_ERROR_NONE; } -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) +typedef struct { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - - pthread_mutex_lock(&surface_queue->lock); - - surface_queue->acquirable_cb = acquirable_cb; - surface_queue->acquirable_cb_data = data; - - pthread_mutex_unlock(&surface_queue->lock); + int queue_size; + int num_attached; + int flags; +}tbm_queue_default; - return TBM_SURFACE_QUEUE_ERROR_NONE; +static void __tbm_queue_default_init(tbm_surface_queue_h surface_queue) +{ } -int tbm_surface_queue_get_queue_size(tbm_surface_queue_h surface_queue) +static void __tbm_queue_default_reset(tbm_surface_queue_h surface_queue) { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0); + tbm_queue_default* data = surface_queue->impl_data; + data->num_attached = 0; +} - return surface_queue->size; +static void __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue) +{ + free(surface_queue->impl_data); } -int tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue) +static void __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue) { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0); + tbm_queue_default* data = surface_queue->impl_data; + tbm_surface_h surface; - return surface_queue->width; + 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++; } -int tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue) +static void __tbm_queue_default_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - return surface_queue->height; + /* Push to back of dirty_queue */ + _tbm_surface_queue_enqueue(surface_queue, surface, 1); } -int tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue) +static void __tbm_queue_default_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface) { - return surface_queue->format; + /* Push to front of free_queue */ + _tbm_surface_queue_release(surface_queue, surface, 0); } -tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_queue, int width, int height, int format) +static void __tbm_queue_default_dequeue(tbm_surface_queue_h surface_queue) { - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - - int i; - queue_node *node = NULL; + /*NOOP*/ +} - if (width == surface_queue->width && height == surface_queue->height && format == surface_queue->format) - return TBM_SURFACE_QUEUE_ERROR_NONE; +static void __tbm_queue_default_acquire(tbm_surface_queue_h surface_queue) +{ + /*NOOP*/ +} - pthread_mutex_lock(&surface_queue->lock); +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, + __tbm_queue_default_enqueue, + __tbm_queue_default_release, + __tbm_queue_default_dequeue, + __tbm_queue_default_acquire +}; - surface_queue->width = width; - surface_queue->height = height; - surface_queue->format = format; +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); - /* Reset queue */ - _queue_init(&surface_queue->free_queue); - _queue_init(&surface_queue->duty_queue); - - /* Destory surface and Push to free_queue */ - for (i = 0; i < surface_queue->size; i++) { - node = surface_queue->node_list[i]; - if (node->surface) { - tbm_surface_destroy(node->surface); - node->surface = 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); - _queue_node_push_back(&surface_queue->free_queue, node); + tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default)); + if (data == NULL) + { + free(surface_queue); + return NULL; } - pthread_mutex_unlock(&surface_queue->lock); - pthread_cond_signal(&surface_queue->free_cond); - - if (surface_queue->reset_cb) - surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data); + data->queue_size = queue_size; + data->flags = flags; + _tbm_surface_queue_init(surface_queue, + width, height, format, + &tbm_queue_default_impl, data); - return TBM_SURFACE_QUEUE_ERROR_NONE; + return surface_queue; } -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) -{ - TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE); - - pthread_mutex_lock(&surface_queue->lock); - - surface_queue->reset_cb = reset_cb; - surface_queue->reset_cb_data = data; - - pthread_mutex_unlock(&surface_queue->lock); - - return TBM_SURFACE_QUEUE_ERROR_NONE; -} diff --git a/src/tbm_surface_queue.h b/src/tbm_surface_queue.h index d61b759..67f576a 100644 --- a/src/tbm_surface_queue.h +++ b/src/tbm_surface_queue.h @@ -72,8 +72,10 @@ 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);