From 0f937a6a9a1cf72b6453a59533bef45c38955d9e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 10 Feb 2017 09:09:35 +0900 Subject: [PATCH] buffer: correct the buffer management Change-Id: Ica59998a4739b95727e0cf19bad8a5387c795d3a --- src/tdm_display.c | 275 +++++++++++++++++++++++++++------------------- src/tdm_private.h | 8 +- 2 files changed, 166 insertions(+), 117 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index bae364ef..5238471f 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -102,7 +102,8 @@ private_output = private_layer->private_output; \ private_display = private_output->private_display -static void _tdm_layer_committed(tdm_private_layer *private_layer); +static void _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer); +static void _tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer); static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); static void _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data); @@ -994,12 +995,12 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, } if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("-----------------------------------------"); + TDM_INFO("----------------------------------------- output(%d) got vblank", private_output->pipe); _pthread_mutex_unlock(&private_display->lock); LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) { if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("output(%d) got vblank: handler(%p)", private_output->pipe, v); + TDM_INFO("handler(%p)", v); if (v->func) v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data); @@ -1047,10 +1048,16 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, return; } + if (tdm_debug_module & TDM_DEBUG_COMMIT) { + TDM_INFO("----------------------------------------- output(%d) committed", private_output->pipe); + TDM_INFO("handler(%p)", output_commit_handler); + } + if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { /* In case of layer commit, the below will be handled in the layer commit callback */ LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { - _tdm_layer_committed(private_layer); + if (private_layer->committed_buffer) + _tdm_layer_committed(private_layer, &private_layer->committed_buffer); } } @@ -1063,6 +1070,9 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, LIST_DEL(&output_commit_handler->link); free(output_commit_handler); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("-----------------------------------------..."); } /* add_front: To distinguish between the user vblank handlers and the layer @@ -1196,6 +1206,8 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, { tdm_func_output *func_output; tdm_private_output_commit_handler *output_commit_handler = NULL; + tdm_private_layer *private_layer = NULL; + OUTPUT_FUNC_ENTRY(); func_output = &private_display->func_output; @@ -1231,7 +1243,19 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("output(%d) backend commit", private_output->pipe); + TDM_INFO("output(%d) backend commit: handle(%p)", private_output->pipe, output_commit_handler); + + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + if (!private_layer->waiting_buffer) + continue; + + private_layer->committed_buffer = private_layer->waiting_buffer; + private_layer->waiting_buffer = NULL; + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)", + private_layer, private_layer->waiting_buffer, + private_layer->committed_buffer->buffer); + } return ret; @@ -1756,6 +1780,96 @@ _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer) return; } +static void +_tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer) +{ + tdm_private_display *private_display; + + if (!layer_buffer) + return; + + private_display = private_layer->private_output->private_display; + + LIST_DEL(&layer_buffer->link); + if (layer_buffer->buffer) { + _pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(layer_buffer->buffer); + if (private_layer->buffer_queue) + tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer); + _pthread_mutex_lock(&private_display->lock); + } + free(layer_buffer); +} + +static void +_tdm_layer_free_all_buffers(tdm_private_layer *private_layer) +{ + tdm_private_output *private_output = private_layer->private_output; + tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; + struct list_head clone_list; + + LIST_INITHEAD(&clone_list); + + if (private_layer->waiting_buffer) { + _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); + private_layer->waiting_buffer = NULL; + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) waiting_buffer(%p)", + private_layer, private_layer->waiting_buffer); + } + + if (private_layer->committed_buffer) { + _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer); + private_layer->committed_buffer = NULL; + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) committed_buffer(%p)", + private_layer, private_layer->committed_buffer); + } + + if (private_layer->showing_buffer) { + _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer); + private_layer->showing_buffer = NULL; + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) showing_buffer(%p)", + private_layer, private_layer->showing_buffer); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { + if (lm->private_layer != private_layer) + continue; + LIST_DEL(&lm->link); + LIST_ADDTAIL(&lm->link, &clone_list); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) { + LIST_DEL(&lm->link); + _tdm_layer_free_buffer(private_layer, lm->committed_buffer); + free(lm); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + if (lm->private_layer != private_layer) + continue; + LIST_DEL(&lm->link); + LIST_ADDTAIL(&lm->link, &clone_list); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) { + LIST_DEL(&lm->link); + _tdm_layer_free_buffer(private_layer, lm->committed_buffer); + free(lm); + } + + if (private_layer->buffer_queue) { + tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer); + tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer); + private_layer->buffer_queue = NULL; + } +} + EXTERN tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) { @@ -1790,12 +1904,13 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) return TDM_ERROR_NOT_IMPLEMENTED; } - layer_buffer = calloc(1, sizeof * layer_buffer); + 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); ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); @@ -1805,15 +1920,8 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) _tdm_layer_dump_buffer(layer, buffer); if (ret == TDM_ERROR_NONE) { - /* FIXME: should save to pending_buffer first. And after committing - * successfully, need to move to waiting_buffer. - */ - if (private_layer->waiting_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->waiting_buffer->buffer); - _pthread_mutex_lock(&private_display->lock); - free(private_layer->waiting_buffer); - } + 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(buffer); @@ -1821,7 +1929,7 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) TDM_INFO("layer(%p) waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer); } else - free(layer_buffer); + _tdm_layer_free_buffer(private_layer, layer_buffer); _pthread_mutex_unlock(&private_display->lock); @@ -1831,7 +1939,6 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) EXTERN tdm_error tdm_layer_unset_buffer(tdm_layer *layer) { - tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); @@ -1839,53 +1946,7 @@ tdm_layer_unset_buffer(tdm_layer *layer) func_layer = &private_display->func_layer; - if (private_layer->buffer_queue) { - if (private_layer->waiting_buffer) - tbm_surface_queue_release(private_layer->buffer_queue, private_layer->waiting_buffer->buffer); - if (private_layer->showing_buffer) - tbm_surface_queue_release(private_layer->buffer_queue, private_layer->showing_buffer->buffer); - tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer); - tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer); - private_layer->buffer_queue = NULL; - } - - if (private_layer->waiting_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->waiting_buffer->buffer); - _pthread_mutex_lock(&private_display->lock); - free(private_layer->waiting_buffer); - private_layer->waiting_buffer = NULL; - - if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) waiting_buffer(%p)", - private_layer, private_layer->waiting_buffer); - } - - if (private_layer->showing_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->showing_buffer->buffer); - _pthread_mutex_lock(&private_display->lock); - free(private_layer->showing_buffer); - private_layer->showing_buffer = NULL; - - if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) showing_buffer(%p)", - private_layer, private_layer->showing_buffer); - } - - LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { - if (lm->private_layer != private_layer) - continue; - LIST_DEL(&lm->link); - free(lm); - } - - LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { - if (lm->private_layer != private_layer) - continue; - LIST_DEL(&lm->link); - free(lm); - } + _tdm_layer_free_all_buffers(private_layer); private_layer->usable = 1; @@ -1907,14 +1968,11 @@ tdm_layer_unset_buffer(tdm_layer *layer) } static void -_tdm_layer_committed(tdm_private_layer *private_layer) +_tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer) { tdm_private_output *private_output = private_layer->private_output; tdm_private_display *private_display = private_output->private_display; - if (!private_layer->waiting_buffer) - return; - if (private_display->print_fps) { double curr = tdm_helper_get_time(); if (private_layer->fps_stamp == 0) { @@ -1930,25 +1988,15 @@ _tdm_layer_committed(tdm_private_layer *private_layer) private_layer->fps_count = 0; } - if (private_layer->showing_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->showing_buffer->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->buffer); - _pthread_mutex_lock(&private_display->lock); - } - } + if (private_layer->showing_buffer) + _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer); - private_layer->showing_buffer = private_layer->waiting_buffer; - private_layer->waiting_buffer = NULL; + private_layer->showing_buffer = *committed_buffer; + *committed_buffer = NULL; if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)", - private_layer, private_layer->waiting_buffer, + TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)", + private_layer, *committed_buffer, (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL); } @@ -1982,14 +2030,17 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) { if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) committed. handle(%p)", lm->private_layer, (lm)?:NULL); + TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)", + lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL); - _tdm_layer_committed(lm->private_layer); + LIST_DEL(&lm->link); + _tdm_layer_committed(lm->private_layer, &lm->committed_buffer); _pthread_mutex_unlock(&private_display->lock); if (lm->func) lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data); _pthread_mutex_lock(&private_display->lock); - LIST_DEL(&lm->link); + if (lm->committed_buffer) + _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer); free(lm); } @@ -2025,6 +2076,7 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se wait_failed: LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) { LIST_DEL(&lm->link); + _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer); free(lm); } return; @@ -2059,11 +2111,11 @@ _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)", - private_layer, private_output->pipe, (layer_commit_handler)?:NULL); + private_layer, private_output->pipe, layer_commit_handler); _pthread_mutex_lock(&private_display->lock); - _tdm_layer_committed(private_layer); + _tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer); if (layer_commit_handler->func) { _pthread_mutex_unlock(&private_display->lock); @@ -2140,6 +2192,14 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da layer_commit_handler->func = func; layer_commit_handler->user_data = user_data; + layer_commit_handler->committed_buffer = private_layer->waiting_buffer; + private_layer->waiting_buffer = NULL; + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)", + private_layer, private_layer->waiting_buffer, + (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL); + if (!private_display->commit_per_vblank) { TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed); @@ -2160,7 +2220,6 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da if (_tdm_layer_commit_possible(private_layer)) { /* add to layer_commit_handler_list */ LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list); - ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); @@ -2199,6 +2258,7 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da commit_failed: if (layer_commit_handler) { + private_layer->waiting_buffer = layer_commit_handler->committed_buffer; LIST_DEL(&layer_commit_handler->link); free(layer_commit_handler); } @@ -2292,12 +2352,13 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) return; } - layer_buffer = calloc(1, sizeof * layer_buffer); + layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer)); if (!layer_buffer) { _pthread_mutex_unlock(&private_display->lock); TDM_ERR("alloc failed"); return; } + LIST_INITHEAD(&layer_buffer->link); if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) || surface == NULL) { @@ -2314,12 +2375,7 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) if (ret == TDM_ERROR_NONE) { if (private_layer->waiting_buffer) { TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer); - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->waiting_buffer->buffer); - tbm_surface_queue_release(private_layer->buffer_queue, - private_layer->waiting_buffer->buffer); - _pthread_mutex_lock(&private_display->lock); - free(private_layer->waiting_buffer); + _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); } private_layer->waiting_buffer = layer_buffer; @@ -2341,7 +2397,7 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) TDM_NEVER_GET_HERE(); } } else - free(layer_buffer); + _tdm_layer_free_buffer(private_layer, layer_buffer); _pthread_mutex_unlock(&private_display->lock); } @@ -2356,18 +2412,10 @@ _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data) _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->buffer); - tbm_surface_queue_release(private_layer->buffer_queue, - private_layer->waiting_buffer->buffer); - _pthread_mutex_lock(&private_display->lock); - free(private_layer->waiting_buffer); - private_layer->waiting_buffer = NULL; - } - private_layer->buffer_queue = NULL; + _tdm_layer_free_all_buffers(private_layer); + _pthread_mutex_unlock(&private_display->lock); } @@ -2400,13 +2448,8 @@ tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) } if (private_layer->waiting_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->waiting_buffer->buffer); - tbm_surface_queue_release(private_layer->buffer_queue, - private_layer->waiting_buffer->buffer); - free(private_layer->waiting_buffer); + _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); private_layer->waiting_buffer = NULL; - _pthread_mutex_lock(&private_display->lock); if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("layer(%p) waiting_buffer(%p)", @@ -2416,10 +2459,10 @@ tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) private_layer->buffer_queue = buffer_queue; tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, - layer); + private_layer); tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, - layer); + private_layer); _pthread_mutex_unlock(&private_display->lock); return ret; diff --git a/src/tdm_private.h b/src/tdm_private.h index 56313775..3e644294 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -230,8 +230,12 @@ struct _tdm_private_layer { tdm_caps_layer caps; tdm_layer *layer_backend; - tdm_private_layer_buffer *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. + */ tdm_private_layer_buffer *waiting_buffer; + tdm_private_layer_buffer *committed_buffer; /* for output_commit */ tdm_private_layer_buffer *showing_buffer; tbm_surface_queue_h buffer_queue; @@ -347,6 +351,8 @@ struct _tdm_private_layer_commit_handler { tdm_private_layer *private_layer; tdm_layer_commit_handler func; void *user_data; + + tdm_private_layer_buffer *committed_buffer; /* for layer_commit */ }; struct _tdm_private_change_handler { -- 2.34.1