layer: pending layer's data until committed 55/151755/1
authorBoram Park <boram1288.park@samsung.com>
Fri, 22 Sep 2017 01:46:16 +0000 (10:46 +0900)
committerBoram Park <boram1288.park@samsung.com>
Fri, 22 Sep 2017 02:03:28 +0000 (11:03 +0900)
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
src/tdm_output.c
src/tdm_private.h

index c6128a8..ea30779 100644 (file)
@@ -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);
 
index f6d780a..b37bf4f 100644 (file)
@@ -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);
index cecf66d..522ae57 100644 (file)
@@ -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);