From f00c5a0988a6cae11042bfbedca88257650f5ee9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 22 Sep 2017 10:46:16 +0900 Subject: [PATCH] layer: pending layer's data until committed The layer's info and buffer information should be applied when tdm_layer_commit called. Otherwise, when we call tdm_layer_commit for A layer, the changes of B layer can be applied to backend unintentionally. Change-Id: I5cfdde9ed9f918174aa5a0785bad48c93c4b2091 --- src/tdm_layer.c | 119 ++++++++++++++++++++++++++++++++++++++++++------------ src/tdm_output.c | 7 ++++ src/tdm_private.h | 8 ++++ 3 files changed, 109 insertions(+), 25 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index c6128a8..ea30779 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -81,6 +81,7 @@ static void _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, vo static void _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data); static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); +static void _tdm_layer_reset_pending_data(tdm_private_layer *private_layer); EXTERN tdm_error tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities) @@ -242,8 +243,8 @@ tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info) info->dst_pos.w, info->dst_pos.h, info->transform); - ret = func_layer->layer_set_info(private_layer->layer_backend, info); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + private_layer->pending_info_changed = 1; + private_layer->pending_info = *info; _pthread_mutex_unlock(&private_display->lock); @@ -335,6 +336,8 @@ _tdm_layer_free_all_buffers(tdm_private_layer *private_layer) LIST_INITHEAD(&clone_list); + _tdm_layer_reset_pending_data(private_layer); + if (private_layer->waiting_buffer) { _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); private_layer->waiting_buffer = NULL; @@ -400,7 +403,6 @@ EXTERN tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) { tdm_func_layer *func_layer; - tdm_private_layer_buffer *layer_buffer; LAYER_FUNC_ENTRY(); @@ -430,32 +432,22 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) return TDM_ERROR_NOT_IMPLEMENTED; } - layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer)); - if (!layer_buffer) { - _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - LIST_INITHEAD(&layer_buffer->link); + private_layer->pending_buffer_changed = 1; - ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + if (private_layer->pending_buffer) { + tbm_surface_internal_unref(private_layer->pending_buffer); - /* dump buffer */ - if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) - _tdm_layer_dump_buffer(layer, buffer); + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) pending_buffer(%p) skipped", + private_layer, private_layer->pending_buffer); + } - if (ret == TDM_ERROR_NONE) { - if (private_layer->waiting_buffer) - _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); + tbm_surface_internal_ref(buffer); + private_layer->pending_buffer = buffer; - private_layer->waiting_buffer = layer_buffer; - private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(buffer); - if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) waiting_buffer(%p)", - private_layer, private_layer->waiting_buffer->buffer); - } else - _tdm_layer_free_buffer(private_layer, layer_buffer); + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) pending_buffer(%p)", + private_layer, private_layer->pending_buffer); _pthread_mutex_unlock(&private_display->lock); @@ -745,6 +737,72 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer) return 1; } +static void +_tdm_layer_reset_pending_data(tdm_private_layer *private_layer) +{ + private_layer->pending_info_changed = 0; + memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info); + + private_layer->pending_buffer_changed = 0; + if (private_layer->pending_buffer) { + tbm_surface_internal_unref(private_layer->pending_buffer); + private_layer->pending_buffer = NULL; + } +} + +INTERN tdm_error +tdm_layer_commit_pending_data(tdm_private_layer *private_layer) +{ + tdm_private_output *private_output = private_layer->private_output; + tdm_private_display *private_display = private_output->private_display; + tdm_func_layer *func_layer; + tdm_error ret = TDM_ERROR_NONE; + + func_layer = &private_display->func_layer; + + if (private_layer->pending_info_changed) { + ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + } + + if (private_layer->pending_buffer_changed) { + tdm_private_layer_buffer *layer_buffer; + + layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer)); + TDM_GOTO_IF_FAIL(layer_buffer != NULL, done); + + LIST_INITHEAD(&layer_buffer->link); + + ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) pending_buffer(%p) committed", + private_layer, private_layer->pending_buffer); + + /* dump buffer */ + if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) + _tdm_layer_dump_buffer(private_layer, private_layer->pending_buffer); + + if (ret == TDM_ERROR_NONE) { + if (private_layer->waiting_buffer) + _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); + + private_layer->waiting_buffer = layer_buffer; + private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer); + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) waiting_buffer(%p)", + private_layer, private_layer->waiting_buffer->buffer); + } else + _tdm_layer_free_buffer(private_layer, layer_buffer); + } + +done: + _tdm_layer_reset_pending_data(private_layer); + + return ret; +} + /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always. * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons, * the layer commit handler MUST be called. @@ -863,6 +921,14 @@ tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_dat return TDM_ERROR_DPMS_OFF; } + /* don't call this inside of _tdm_layer_commit */ + ret = tdm_layer_commit_pending_data(private_layer); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("layer(%p) committing pending data failed", layer); + _pthread_mutex_unlock(&private_display->lock); + return ret; + } + ret = _tdm_layer_commit(private_layer, func, user_data); _pthread_mutex_unlock(&private_display->lock); @@ -991,6 +1057,9 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) return; } + /* we don't need to handle pending data here because the changes in this function + * should be applied immediately. we can't expect calling tdm_layer_commit. + */ ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); diff --git a/src/tdm_output.c b/src/tdm_output.c index f6d780a..b37bf4f 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -960,6 +960,8 @@ EXTERN tdm_error tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { + tdm_private_layer *private_layer = NULL; + OUTPUT_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); @@ -988,6 +990,11 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("output(%d) commit", private_output->pipe); + /* apply the pending data of all layers */ + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + tdm_layer_commit_pending_data(private_layer); + } + ret = tdm_output_commit_internal(output, sync, func, user_data); _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index cecf66d..522ae57 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -233,6 +233,12 @@ struct _tdm_private_layer { tdm_caps_layer caps; tdm_layer *layer_backend; + /* pending data until committed */ + unsigned int pending_info_changed; + tdm_info_layer pending_info; + unsigned int pending_buffer_changed; + tbm_surface_h pending_buffer; + /* When a buffer is set to a layer, it will be stored to waiting_buffer. * And when a layer is committed, it will be moved to committed_buffer. * Finally when a commit handler is called, it will be moved to showing_buffer. @@ -436,6 +442,8 @@ tdm_output_remove_commit_handler_internal(tdm_output *output, tdm_output_commit_ void tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data); +tdm_error +tdm_layer_commit_pending_data(tdm_private_layer *private_layer); void tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer); -- 2.7.4