tbm_surface_queue: called need_attach when queue_dequeue
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
index 51fcfc0..1dadcb0 100644 (file)
@@ -29,6 +29,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
+#include "config.h"
+
 #include "tbm_bufmgr_int.h"
 #include "list.h"
 
@@ -104,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);
@@ -114,6 +123,7 @@ typedef struct _tbm_surface_queue_interface {
        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);
+       void (*need_detach)(tbm_surface_queue_h queue, queue_node *node);
 } tbm_surface_queue_interface;
 
 struct _tbm_surface_queue {
@@ -121,6 +131,7 @@ struct _tbm_surface_queue {
        int height;
        int format;
        int queue_size;
+       int num_attached;
 
        queue free_queue;
        queue dirty_queue;
@@ -129,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;
@@ -158,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;
        }
 
@@ -167,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);
@@ -201,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;
 }
 
@@ -264,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;
@@ -277,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;
@@ -288,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;
@@ -296,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)
@@ -308,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)
@@ -320,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;
@@ -330,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;
 }
 
@@ -378,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) {
@@ -394,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);
@@ -406,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++;
        }
@@ -428,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);
@@ -441,22 +534,25 @@ _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
        node->surface = surface;
 
        LIST_ADDTAIL(&node->link, &surface_queue->list);
+       surface_queue->num_attached++;
        _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);
-       if (node)
+       if (node) {
                _queue_delete_node(surface_queue, node);
+               surface_queue->num_attached--;
+       }
 }
 
-void
+static void
 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
                           queue_node *node, int push_back)
 {
@@ -466,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;
@@ -497,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)
 {
@@ -507,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,
@@ -516,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();
 
@@ -537,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);
@@ -687,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)
@@ -733,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,
@@ -881,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();
@@ -900,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)
@@ -918,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;
@@ -928,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;
@@ -937,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,
@@ -948,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;
 
@@ -979,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;
@@ -991,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);
@@ -1000,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();
@@ -1061,12 +1257,30 @@ 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)
+                       surface_queue->impl->need_detach(surface_queue, node);
+               else
+                       _tbm_surface_queue_detach(surface_queue, surface);
+
+               pthread_mutex_unlock(&surface_queue->lock);
+
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_SURFACE_QUEUE_ERROR_NONE;
        }
 
        if (surface_queue->impl && surface_queue->impl->release)
@@ -1077,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;
@@ -1088,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;
@@ -1097,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,
@@ -1113,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;
@@ -1143,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;
 }
 
@@ -1157,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();
 
@@ -1203,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);
@@ -1213,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();
@@ -1234,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();
 
@@ -1244,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;
        }
@@ -1256,15 +1463,16 @@ 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);
        _queue_init(&surface_queue->dirty_queue);
        LIST_INITHEAD(&surface_queue->list);
 
+       surface_queue->num_attached = 0;
+
        if (surface_queue->impl && surface_queue->impl->reset)
                surface_queue->impl->reset(surface_queue);
 
@@ -1279,29 +1487,160 @@ tbm_surface_queue_reset(tbm_surface_queue_h
 }
 
 tbm_surface_queue_error_e
-tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
+tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
 {
-       queue_node *node = NULL, *tmp = 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_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;
+
+       _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_RETURN_VAL_IF_FAIL(queue_size > 0,
+                                       TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       if ((surface_queue->queue_size == queue_size) && !flush) {
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_SURFACE_QUEUE_ERROR_NONE;
+       }
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       if (flush) {
+               /* Destory surface and Push to free_queue */
+               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);
+               _queue_init(&surface_queue->dirty_queue);
+               LIST_INITHEAD(&surface_queue->list);
+
+               surface_queue->num_attached = 0;
+               surface_queue->queue_size = queue_size;
+
+               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);
+
+               _tbm_surf_queue_mutex_unlock();
+
+               _notify_emit(surface_queue, &surface_queue->reset_noti);
+
+               return TBM_SURFACE_QUEUE_ERROR_NONE;
+       } else {
+               if (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)
+                                       surface_queue->impl->need_detach(surface_queue, node);
+                               else
+                                       _tbm_surface_queue_detach(surface_queue, node->surface);
+
+                               need_del--;
+                               if (need_del == 0)
+                                       break;
+                       }
+               }
+
+               surface_queue->queue_size = queue_size;
+
+               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_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;
+
+       _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 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);
        _queue_init(&surface_queue->dirty_queue);
        LIST_INITHEAD(&surface_queue->list);
 
+       surface_queue->num_attached = 0;
+
        if (surface_queue->impl && surface_queue->impl->reset)
                surface_queue->impl->reset(surface_queue);
 
@@ -1320,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,
@@ -1331,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;
 
@@ -1346,28 +1685,50 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
        return TBM_SURFACE_QUEUE_ERROR_NONE;
 }
 
-typedef struct {
-       int queue_size;
-       int num_attached;
-       int flags;
-} tbm_queue_default;
-
-static void
-__tbm_queue_default_init(tbm_surface_queue_h surface_queue)
+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_queue_default *data = surface_queue->impl_data;
+       _tbm_surf_queue_mutex_lock();
 
-       data->num_attached = 0;
-}
+       *num = 0;
 
-static void
-__tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
-{
-       tbm_queue_default *data = surface_queue->impl_data;
+       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);
 
-       data->num_attached = 0;
+       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;
+
 static void
 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
 {
@@ -1377,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 (data->queue_size == data->num_attached)
+       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;
 
@@ -1402,18 +1766,18 @@ __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
 
        _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 = {
-       __tbm_queue_default_init,
-       __tbm_queue_default_reset,
+       NULL,                           /*__tbm_queue_default_init*/
+       NULL,                           /*__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*/
+       NULL,                           /*__tbm_queue_default_need_detach*/
 };
 
 tbm_surface_queue_h
@@ -1436,15 +1800,15 @@ 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;
        }
 
-       data->queue_size = queue_size;
        data->flags = flags;
        _tbm_surface_queue_init(surface_queue,
-                               data->queue_size,
+                               queue_size,
                                width, height, format,
                                &tbm_queue_default_impl, data);
 
@@ -1454,8 +1818,6 @@ tbm_surface_queue_create(int queue_size, int width,
 }
 
 typedef struct {
-       int queue_size;
-       int num_attached;
        int flags;
        queue dequeue_list;
 } tbm_queue_sequence;
@@ -1463,18 +1825,16 @@ 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;
 
-       data->num_attached = 0;
        _queue_init(&data->dequeue_list);
 }
 
 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;
 
-       data->num_attached = 0;
        _queue_init(&data->dequeue_list);
 }
 
@@ -1487,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 (data->queue_size == data->num_attached)
+       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;
 
@@ -1512,16 +1875,14 @@ __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
 
        _tbm_surface_queue_attach(surface_queue, surface);
        tbm_surface_internal_unref(surface);
-       data->num_attached++;
 }
 
 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;
 
@@ -1537,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) {
@@ -1558,6 +1919,7 @@ static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
        NULL,                                   /*__tbm_queue_sequence_release*/
        __tbm_queue_sequence_dequeue,
        NULL,                                   /*__tbm_queue_sequence_acquire*/
+       NULL,                                   /*__tbm_queue_sequence_need_dettach*/
 };
 
 tbm_surface_queue_h
@@ -1580,14 +1942,15 @@ 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;
        }
 
-       data->queue_size = queue_size;
        data->flags = flags;
        _tbm_surface_queue_init(surface_queue,
-                               data->queue_size,
+                               queue_size,
                                width, height, format,
                                &tbm_queue_sequence_impl, data);