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);
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;
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;
}
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);
}
{
tbm_surface_queue_h old_data = NULL;
- if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
- TBM_TRACE("error: surface_queue is NULL or not initialized\n");
+ if (surface_queue == NULL) {
+ TBM_LOG_E("error: surface_queue is NULL.\n");
+ return 0;
+ }
+
+ 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_TRACE("error: surf_queue_list is empty\n");
+ TBM_LOG_E("error: surf_queue_list is empty\n");
return 0;
}
}
}
- TBM_TRACE("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
+ TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
+
return 0;
}
{
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;
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;
}
}
+ TBM_LOG_E("fail to get the queue_node.\n");
+
return NULL;
}
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;
- 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;
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);
}
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,
pthread_mutex_unlock(&surface_queue->lock);
_tbm_surf_queue_mutex_unlock();
- return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
+
+ 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)
pthread_mutex_unlock(&surface_queue->lock);
_tbm_surf_queue_mutex_unlock();
- return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
+ return TBM_SURFACE_QUEUE_ERROR_EMPTY;
}
node->type = QUEUE_NODE_TYPE_ENQUEUE;
_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;
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
pthread_mutex_unlock(&surface_queue->lock);
_tbm_surf_queue_mutex_unlock();
- return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
+ return TBM_SURFACE_QUEUE_ERROR_EMPTY;
}
node->type = QUEUE_NODE_TYPE_DEQUEUE;
_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;
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 0;
}
_tbm_surf_queue_mutex_lock();
if (!_tbm_surface_queue_is_valid(surface_queue)) {
- TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+ TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
pthread_mutex_unlock(&surface_queue->lock);
- _tbm_surf_queue_mutex_unlock();
- return 0;
+ _tbm_surf_queue_mutex_unlock();
+ return 0;
}
pthread_mutex_unlock(&surface_queue->lock);
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) {
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_INVALID_SURFACE;
+ return TBM_SURFACE_QUEUE_ERROR_EMPTY;
}
node->type = QUEUE_NODE_TYPE_RELEASE;
_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;
pthread_mutex_unlock(&surface_queue->lock);
_tbm_surf_queue_mutex_unlock();
- return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
+ return TBM_SURFACE_QUEUE_ERROR_EMPTY;
}
node->type = QUEUE_NODE_TYPE_ACQUIRE;
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;
}
_tbm_surf_queue_mutex_lock();
if (!_tbm_surface_queue_is_valid(surface_queue)) {
- TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+ TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
pthread_mutex_unlock(&surface_queue->lock);
- _tbm_surf_queue_mutex_unlock();
- return 0;
+ _tbm_surf_queue_mutex_unlock();
+ return 0;
}
pthread_mutex_unlock(&surface_queue->lock);
_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);
}
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;
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;
_tbm_surf_queue_mutex_lock();
pthread_mutex_lock(&surface_queue->lock);
+ /* silent return */
if (!surface)
return;
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;
_tbm_surf_queue_mutex_lock();
pthread_mutex_lock(&surface_queue->lock);
+ /* silent return */
if (!surface)
return;
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;