#include "tbm_bufmgr_int.h"
#include "list.h"
+#include <time.h>
#define FREE_QUEUE 1
#define DIRTY_QUEUE 2
#define NODE_LIST 4
static tbm_bufmgr g_surf_queue_bufmgr;
-static pthread_mutex_t tbm_surf_queue_lock;
+static pthread_mutex_t tbm_surf_queue_lock = PTHREAD_MUTEX_INITIALIZER;
void _tbm_surface_queue_mutex_unlock(void);
/* check condition */
int height;
int format;
int queue_size;
+ int flags;
int num_attached;
queue free_queue;
unsigned int acquire_sync_count;
};
-static bool
-_tbm_surf_queue_mutex_init(void)
-{
- static bool tbm_surf_queue_mutex_init = false;
-
- if (tbm_surf_queue_mutex_init)
- return true;
-
- if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
- TBM_ERR("fail: pthread_mutex_init\n");
- return false;
- }
-
- tbm_surf_queue_mutex_init = true;
-
- return true;
-}
-
static void
_tbm_surf_queue_mutex_lock(void)
{
- if (!_tbm_surf_queue_mutex_init()) {
- TBM_ERR("fail: _tbm_surf_queue_mutex_init\n");
- return;
- }
-
pthread_mutex_lock(&tbm_surf_queue_lock);
}
LIST_FOR_EACH_ENTRY(old_data, &g_surf_queue_bufmgr->surf_queue_list,
item_link) {
- if (old_data == surface_queue) {
- TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
+ if (old_data == surface_queue)
return 1;
- }
}
TBM_ERR("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
}
static void
+_tbm_surface_queue_need_attach(tbm_surface_queue_h surface_queue)
+{
+ tbm_surface_h surface;
+
+ if (surface_queue->queue_size == surface_queue->num_attached)
+ return;
+
+ if (surface_queue->alloc_cb) {
+ surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
+
+ /* silent return */
+ if (!surface)
+ return;
+
+ tbm_surface_internal_ref(surface);
+ } else {
+ surface = tbm_surface_internal_create_with_flags(surface_queue->width,
+ surface_queue->height,
+ surface_queue->format,
+ surface_queue->flags);
+ TBM_RETURN_IF_FAIL(surface != NULL);
+ }
+
+ _tbm_surface_queue_attach(surface_queue, surface);
+ tbm_surface_internal_unref(surface);
+}
+
+static void
_tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
tbm_surface_h surface)
{
static void
_tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
int queue_size,
- int width, int height, int format,
+ int width, int height, int format, int flags,
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);
_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;
surface_queue->height = height;
surface_queue->format = format;
+ surface_queue->flags = flags;
surface_queue->impl = impl;
surface_queue->impl_data = data;
surface_queue->modes = TBM_SURFACE_QUEUE_MODE_NONE;
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;
- }
+ else
+ _tbm_surface_queue_need_attach(surface_queue);
}
if (surface_queue->impl && surface_queue->impl->dequeue)
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);
+ else
+ _tbm_surface_queue_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 {
+ if (surface_queue->impl && surface_queue->impl->need_attach)
+ surface_queue->impl->need_attach(surface_queue);
+ else
+ _tbm_surface_queue_need_attach(surface_queue);
+
+ if (!_queue_is_empty(&surface_queue->free_queue)) {
+ 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)
{
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;
- }
+ else
+ _tbm_surface_queue_need_attach(surface_queue);
}
if (!_queue_is_empty(&surface_queue->free_queue)) {
if (wait) {
_tbm_surf_queue_mutex_unlock();
- pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
- pthread_mutex_unlock(&surface_queue->lock);
- return 1;
+ while (1) {
+ pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
+
+ if (surface_queue->impl && surface_queue->impl->need_attach)
+ surface_queue->impl->need_attach(surface_queue);
+ else
+ _tbm_surface_queue_need_attach(surface_queue);
+
+ if (!_queue_is_empty(&surface_queue->free_queue)) {
+ pthread_mutex_unlock(&surface_queue->lock);
+ return 1;
+ }
+ }
}
pthread_mutex_unlock(&surface_queue->lock);
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)
-{
- free(surface_queue->impl_data);
-}
-
-static void
-__tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
-{
- tbm_queue_default *data = (tbm_queue_default *)surface_queue->impl_data;
- tbm_surface_h surface;
-
- if (surface_queue->queue_size == surface_queue->num_attached)
- return;
-
- if (surface_queue->alloc_cb) {
- surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
-
- /* silent return */
- if (!surface)
- return;
-
- tbm_surface_internal_ref(surface);
- } else {
- 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);
-}
-
static const tbm_surface_queue_interface tbm_queue_default_impl = {
NULL, /*__tbm_queue_default_init*/
NULL, /*__tbm_queue_default_reset*/
- __tbm_queue_default_destroy,
- __tbm_queue_default_need_attach,
+ NULL, /*__tbm_queue_default_destroy*/
+ NULL, /*__tbm_queue_default_need_attach*/
NULL, /*__tbm_queue_default_enqueue*/
NULL, /*__tbm_queue_default_release*/
NULL, /*__tbm_queue_default_dequeue*/
TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
- tbm_queue_default *data = (tbm_queue_default *) calloc(1,
- sizeof(tbm_queue_default));
- if (data == NULL) {
- TBM_ERR("cannot allocate the tbm_queue_default.\n");
- _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
- free(surface_queue);
- _tbm_surf_queue_mutex_unlock();
- return NULL;
- }
-
- data->flags = flags;
_tbm_surface_queue_init(surface_queue,
queue_size,
- width, height, format,
- &tbm_queue_default_impl, data);
+ width, height, format, flags,
+ &tbm_queue_default_impl, NULL);
_tbm_surf_queue_mutex_unlock();
}
typedef struct {
- int flags;
queue dequeue_list;
} tbm_queue_sequence;
}
static void
-__tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
-{
- tbm_queue_sequence *data = (tbm_queue_sequence *)surface_queue->impl_data;
- tbm_surface_h surface;
-
- if (surface_queue->queue_size == surface_queue->num_attached)
- return;
-
- if (surface_queue->alloc_cb) {
- surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
-
- /* silent return */
- if (!surface)
- return;
-
- tbm_surface_internal_ref(surface);
- } else {
- 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);
-}
-
-static void
__tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
queue_node *node)
{
__tbm_queue_sequence_init,
__tbm_queue_sequence_reset,
__tbm_queue_sequence_destroy,
- __tbm_queue_sequence_need_attach,
+ NULL,
__tbm_queue_sequence_enqueue,
__tbm_queue_sequence_release,
__tbm_queue_sequence_dequeue,
return NULL;
}
- data->flags = flags;
_tbm_surface_queue_init(surface_queue,
queue_size,
- width, height, format,
+ width, height, format, flags,
&tbm_queue_sequence_impl, data);
_tbm_surf_queue_mutex_unlock();