+ node->type = QUEUE_NODE_TYPE_DEQUEUE;
+ *surface = node->surface;
+
+ TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
+
+ pthread_mutex_unlock(&surface_queue->lock);
+
+ _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;
+}
+
+int
+tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
+{
+ _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), 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_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 (!_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)) {
+ pthread_mutex_unlock(&surface_queue->lock);
+ _tbm_surf_queue_mutex_unlock();
+ return 1;
+ }
+
+ 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);
+ pthread_mutex_unlock(&surface_queue->lock);
+ return 1;
+ }
+
+ pthread_mutex_unlock(&surface_queue->lock);
+ _tbm_surf_queue_mutex_unlock();
+ return 0;
+}
+
+tbm_surface_queue_error_e
+tbm_surface_queue_release(tbm_surface_queue_h
+ surface_queue, tbm_surface_h surface)
+{
+ queue_node *node;
+ int queue_type;
+
+ _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_RETURN_VAL_IF_FAIL(surface != NULL,
+ TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
+
+ pthread_mutex_lock(&surface_queue->lock);
+
+ TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
+
+ node = _queue_get_node(surface_queue, 0, surface, &queue_type);
+ if (node == NULL || queue_type != NODE_LIST) {
+ TBM_ERR("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();
+
+ if (!node) {
+ _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE);
+ return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
+ } else {
+ _tbm_set_last_result(TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST);
+ return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
+ }
+ }
+
+ if (node->delete_pending) {
+ TBM_TRACE_SURFACE_QUEUE("delete pending tbm_surface_queue(%p) surface(%p)\n", surface_queue, node->surface);
+
+ _queue_delete_node(surface_queue, node);
+
+ pthread_mutex_unlock(&surface_queue->lock);
+
+ _tbm_surf_queue_mutex_unlock();
+
+ _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
+
+ return TBM_SURFACE_QUEUE_ERROR_NONE;
+ }