From 2e6071fd6c20db032d71e6da5cb8419531bdf6d4 Mon Sep 17 00:00:00 2001 From: Sangjin Lee Date: Fri, 5 Feb 2016 13:29:33 +0900 Subject: [PATCH] Support tbm_surface_queue Change-Id: Ia18d4d002623efd0b2f606b21e9bb7e96661c28b --- include/tdm.h | 21 ++++++ src/tdm_display.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/tdm_private.h | 4 + 3 files changed, 226 insertions(+), 15 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index 918de10..8380c3c 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -38,6 +38,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include #include #include "tdm_types.h" @@ -465,6 +466,26 @@ tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); tdm_error tdm_layer_unset_buffer(tdm_layer *layer); /** + * @brief Set a TBM surface_queue to a layer object + * @details A TBM surface_queue will be applied when the output object + * of a layer object is committed. and TDM layer will be automatically updated + * @param[in] layer A layer object + * @param[in] buffer_queue A TBM surface_queue + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_commit + */ +tdm_error tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue); + +/** + * @brief Unset a TBM surface_queue from a layer object + * @details When this function is called, a current surface_queue will be + * disappeared from screen. Then nothing is showing on a layer object. + * @param[in] layer A layer object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_unset_buffer_queue(tdm_layer *layer); + +/** * @brief Check wheter a layer object is available for a frontend user to use. * @details A layer object is not usable if a TDM buffer is showing on screen * via this layer object. By calling #tdm_layer_unset_buffer, this layer object diff --git a/src/tdm_display.c b/src/tdm_display.c index cad2151..72d69ad 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -91,6 +91,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. private_output = private_layer->private_output; \ private_display = private_output->private_display +#define LAYER_FUNC_ENTRY_VOID_RETURN() \ + tdm_private_display *private_display; \ + tdm_private_output *private_output; \ + tdm_private_layer *private_layer; \ + tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\ + TDM_RETURN_IF_FAIL(layer != NULL); \ + private_layer = (tdm_private_layer*)layer; \ + private_output = private_layer->private_output; \ + private_display = private_output->private_display + EXTERN tdm_error tdm_display_get_capabilities(tdm_display *dpy, tdm_display_capability *capabilities) { @@ -633,14 +643,6 @@ _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, private_output = commit_handler->private_output; private_display = private_output->private_display; - if (commit_handler->func) - { - pthread_mutex_unlock(&private_display->lock); - commit_handler->func(private_output, sequence, - tv_sec, tv_usec, commit_handler->user_data); - pthread_mutex_lock(&private_display->lock); - } - LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { if (!private_layer->waiting_buffer) @@ -651,12 +653,28 @@ _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(private_layer->showing_buffer); pthread_mutex_lock(&private_display->lock); + + if (private_layer->buffer_queue) + { + pthread_mutex_unlock(&private_display->lock); + tbm_surface_queue_release(private_layer->buffer_queue, + private_layer->showing_buffer); + pthread_mutex_lock(&private_display->lock); + } } private_layer->showing_buffer = private_layer->waiting_buffer; private_layer->waiting_buffer = NULL; } + if (commit_handler->func) + { + pthread_mutex_unlock(&private_display->lock); + commit_handler->func(private_output, sequence, + tv_sec, tv_usec, commit_handler->user_data); + pthread_mutex_lock(&private_display->lock); + } + LIST_DEL(&commit_handler->link); free(commit_handler); } @@ -712,20 +730,17 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return ret; } -EXTERN tdm_error -tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) +static tdm_error +_tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { tdm_func_display *func_display; tdm_private_commit_handler *commit_handler; OUTPUT_FUNC_ENTRY(); - pthread_mutex_lock(&private_display->lock); - func_display = &private_display->func_display; if (!func_display->output_commit) { - pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; } @@ -733,7 +748,6 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, if (!commit_handler) { TDM_ERR("failed: alloc memory"); - pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_OUT_OF_MEMORY; } @@ -745,7 +759,6 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, ret = func_display->output_commit(private_output->output_backend, sync, commit_handler); if (ret != TDM_ERROR_NONE) { - pthread_mutex_unlock(&private_display->lock); return ret; } @@ -756,6 +769,18 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, _tdm_output_cb_commit); } + return ret; +} + +EXTERN tdm_error +tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) +{ + OUTPUT_FUNC_ENTRY(); + + pthread_mutex_lock(&private_display->lock); + + ret = _tdm_output_commit(output, sync, func, user_data); + pthread_mutex_unlock(&private_display->lock); return ret; @@ -1125,6 +1150,167 @@ tdm_layer_unset_buffer(tdm_layer *layer) return ret; } +static void +_tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) +{ + TDM_RETURN_IF_FAIL(data != NULL); + tdm_layer *layer = data; + tdm_func_display *func_display; + tbm_surface_h surface = NULL; + LAYER_FUNC_ENTRY_VOID_RETURN(); + + pthread_mutex_lock(&private_display->lock); + + func_display = &private_display->func_display; + if (!func_display->layer_set_buffer) + { + pthread_mutex_unlock(&private_display->lock); + return; + } + + if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) || + surface == NULL) + { + TDM_ERR("tbm_surface_queue_acquire() failed surface:%p", surface); + pthread_mutex_unlock(&private_display->lock); + return; + } + + if (private_layer->waiting_buffer) + { + pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->waiting_buffer); + tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer); + pthread_mutex_lock(&private_display->lock); + } + + private_layer->waiting_buffer = tdm_buffer_ref_backend(surface); + + func_display->layer_set_buffer(private_layer->layer_backend, surface); + + ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_output_commit() is fail"); + + pthread_mutex_unlock(&private_display->lock); +} + +static void +_tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data) +{ + TDM_RETURN_IF_FAIL(data != NULL); + tdm_layer *layer = data; + LAYER_FUNC_ENTRY_VOID_RETURN(); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + + pthread_mutex_lock(&private_display->lock); + + if (private_layer->waiting_buffer) + { + pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->waiting_buffer); + tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer); + pthread_mutex_lock(&private_display->lock); + } + + private_layer->buffer_queue = NULL; + + pthread_mutex_unlock(&private_display->lock); +} + +EXTERN tdm_error +tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) +{ + tdm_func_display *func_display; + LAYER_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER); + + pthread_mutex_lock(&private_display->lock); + + func_display = &private_display->func_display; + + private_layer->usable = 0; + + if (!func_display->layer_set_buffer) + { + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + if (buffer_queue == private_layer->buffer_queue) + { + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + if (private_layer->waiting_buffer) + { + pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->waiting_buffer); + tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer); + private_layer->waiting_buffer = NULL; + pthread_mutex_lock(&private_display->lock); + } + + private_layer->buffer_queue = buffer_queue; + tbm_surface_queue_set_acquirable_cb(private_layer->buffer_queue, + _tbm_layer_queue_acquirable_cb, + layer); + tbm_surface_queue_set_destroy_cb(private_layer->buffer_queue, + _tbm_layer_queue_destroy_cb, + layer); + pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN tdm_error +tdm_layer_unset_buffer_queue(tdm_layer *layer) +{ + tdm_func_display *func_display; + LAYER_FUNC_ENTRY(); + + pthread_mutex_lock(&private_display->lock); + + func_display = &private_display->func_display; + + if (private_layer->waiting_buffer) + { + pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->waiting_buffer); + tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer); + private_layer->waiting_buffer = NULL; + pthread_mutex_lock(&private_display->lock); + } + + if (private_layer->showing_buffer) + { + pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->showing_buffer); + tbm_surface_queue_release(private_layer->buffer_queue, private_layer->showing_buffer); + pthread_mutex_lock(&private_display->lock); + private_layer->showing_buffer = NULL; + } + + tbm_surface_queue_set_acquirable_cb(private_layer->buffer_queue, NULL, NULL); + tbm_surface_queue_set_destroy_cb(private_layer->buffer_queue, NULL, NULL); + private_layer->buffer_queue = NULL; + private_layer->usable = 1; + + if (!func_display->layer_unset_buffer) + { + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + ret = func_display->layer_unset_buffer(private_layer->layer_backend); + + pthread_mutex_unlock(&private_display->lock); + + return ret; +} + EXTERN tdm_error tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable) { diff --git a/src/tdm_private.h b/src/tdm_private.h index 98e5c07..966edec 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -49,6 +49,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +#include + #include "tdm_backend.h" #include "tdm_log.h" #include "tdm_list.h" @@ -213,6 +216,7 @@ struct _tdm_private_layer tbm_surface_h waiting_buffer; tbm_surface_h showing_buffer; + tbm_surface_queue_h buffer_queue; struct list_head capture_list; -- 2.7.4