Fix tiled format issue.
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
index 5c706e7..b8e85ee 100644 (file)
@@ -33,6 +33,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "tbm_bufmgr_int.h"
 #include "list.h"
+#include <time.h>
 
 #define FREE_QUEUE     1
 #define DIRTY_QUEUE    2
@@ -591,6 +592,8 @@ _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
                        int width, int height, int format,
                        const tbm_surface_queue_interface *impl, void *data)
 {
+       pthread_condattr_t free_attr, dirty_attr;
+
        TBM_RETURN_IF_FAIL(surface_queue != NULL);
        TBM_RETURN_IF_FAIL(impl != NULL);
 
@@ -598,8 +601,16 @@ _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
                _init_tbm_surf_queue_bufmgr();
 
        pthread_mutex_init(&surface_queue->lock, NULL);
-       pthread_cond_init(&surface_queue->free_cond, NULL);
-       pthread_cond_init(&surface_queue->dirty_cond, NULL);
+
+       pthread_condattr_init(&free_attr);
+       pthread_condattr_setclock(&free_attr, CLOCK_MONOTONIC);
+       pthread_cond_init(&surface_queue->free_cond, &free_attr);
+       pthread_condattr_destroy(&free_attr);
+
+       pthread_condattr_init(&dirty_attr);
+       pthread_condattr_setclock(&dirty_attr, CLOCK_MONOTONIC);
+       pthread_cond_init(&surface_queue->dirty_cond, &dirty_attr);
+       pthread_condattr_destroy(&dirty_attr);
 
        surface_queue->queue_size = queue_size;
        surface_queue->width = width;
@@ -1267,14 +1278,6 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h
        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_ERR("surface_queue:%p is invalid", surface_queue);
-                       _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_INVALID_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)
@@ -1307,6 +1310,73 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h
        return TBM_SURFACE_QUEUE_ERROR_NONE;
 }
 
+tbm_surface_queue_error_e
+tbm_surface_queue_can_dequeue_wait_timeout(tbm_surface_queue_h surface_queue, int ms_timeout)
+{
+       int ret;
+       struct timespec tp;
+
+       _tbm_surf_queue_mutex_lock();
+       _tbm_set_last_result(TBM_ERROR_NONE);
+
+       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->can_dequeue_noti);
+
+       _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_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
+
+       if (_queue_is_empty(&surface_queue->free_queue)) {
+               if (surface_queue->impl && surface_queue->impl->need_attach)
+                       surface_queue->impl->need_attach(surface_queue);
+       }
+
+       if (!_queue_is_empty(&surface_queue->free_queue)) {
+               pthread_mutex_unlock(&surface_queue->lock);
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_SURFACE_QUEUE_ERROR_NONE;
+       }
+
+       _tbm_surf_queue_mutex_unlock();
+
+       while (1) {
+               clock_gettime(CLOCK_MONOTONIC, &tp);
+
+               if (ms_timeout > 1000)
+                       tp.tv_sec += ms_timeout / 1000;
+
+               tp.tv_nsec += (ms_timeout % 1000) * 1000000;
+
+               if (tp.tv_nsec > 1000000000L) {
+                       tp.tv_sec++;
+                       tp.tv_nsec -= 1000000000L;
+               }
+
+               ret = pthread_cond_timedwait(&surface_queue->free_cond, &surface_queue->lock, &tp);
+               if (ret) {
+                       if (ret == ETIMEDOUT) {
+                               TBM_ERR("surface_queue:%p can dequeue wait timeout", surface_queue);
+                               pthread_mutex_unlock(&surface_queue->lock);
+                               return TBM_SURFACE_QUEUE_ERROR_TIMEOUT;
+                       } else {
+                               TBM_INFO("surface_queue:%p timedwait error retry wait", surface_queue);
+                       }
+               } else {
+                       pthread_mutex_unlock(&surface_queue->lock);
+                       return TBM_SURFACE_QUEUE_ERROR_NONE;
+               }
+       }
+}
+
 int
 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
 {
@@ -1330,13 +1400,6 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
        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_ERR("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)) {
@@ -1728,6 +1791,10 @@ tbm_surface_queue_notify_dequeuable(tbm_surface_queue_h surface_queue)
        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);
+       pthread_mutex_unlock(&surface_queue->lock);
+       pthread_cond_signal(&surface_queue->free_cond);
+
        _tbm_surf_queue_mutex_unlock();
 
        _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
@@ -1951,6 +2018,37 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
 }
 
 tbm_surface_queue_error_e
+tbm_surface_queue_get_acquirable_surfaces(tbm_surface_queue_h surface_queue,
+                       tbm_surface_h *surfaces, int *num)
+{
+       queue_node *node = 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,
+                              TBM_ERROR_INVALID_PARAMETER);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       LIST_FOR_EACH_ENTRY(node, &surface_queue->dirty_queue.head, item_link) {
+               if (surfaces)
+                       surfaces[*num] = node->surface;
+
+               *num = *num + 1;
+       }
+
+       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_get_trace_surface_num(
                        tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
 {
@@ -2013,11 +2111,7 @@ __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
                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)
@@ -2132,11 +2226,7 @@ __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
                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)