Refactoring tbm_surface_queue 76/58676/2
authorSangjin Lee <lsj119@samsung.com>
Mon, 1 Feb 2016 10:24:17 +0000 (19:24 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Thu, 4 Feb 2016 01:13:07 +0000 (17:13 -0800)
Change-Id: I2b01d213a3eed54a608086b0427a63336cc5df6c

src/tbm_surface_queue.c
src/tbm_surface_queue.h

index 5757a33..daa5626 100644 (file)
@@ -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;
-}
index d61b759..67f576a 100644 (file)
@@ -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);