buffer: correct the buffer management 99/114099/2
authorBoram Park <boram1288.park@samsung.com>
Fri, 10 Feb 2017 00:09:35 +0000 (09:09 +0900)
committerBoram Park <boram1288.park@samsung.com>
Fri, 10 Feb 2017 04:29:22 +0000 (13:29 +0900)
Change-Id: Ica59998a4739b95727e0cf19bad8a5387c795d3a

src/tdm_display.c
src/tdm_private.h

index bae364effa1b01f3314ae9454daaf45d8195fd3d..5238471fc2dea5b55bbe0974a84b364d842506e6 100644 (file)
        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;
index 56313775e60f0f7de9026c662978ad615e20a8df..3e644294407c01a741fb346c9e64c108ed94843e 100644 (file)
@@ -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 {