layer: add tdm_layer_unset_buffer_internal
[platform/core/uifw/libtdm.git] / src / tdm_layer.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
7  * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8  *          JinYoung Jeon <jy0.jeon@samsung.com>,
9  *          Taeheon Kim <th908.kim@samsung.com>,
10  *          YoungJun Cho <yj44.cho@samsung.com>,
11  *          SooChan Lim <sc1.lim@samsung.com>,
12  *          Boram Park <sc1.lim@samsung.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the
16  * "Software"), to deal in the Software without restriction, including
17  * without limitation the rights to use, copy, modify, merge, publish,
18  * distribute, sub license, and/or sell copies of the Software, and to
19  * permit persons to whom the Software is furnished to do so, subject to
20  * the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33  *
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm_private.h"
41
42 #define COUNT_MAX   10
43
44 #define LAYER_FUNC_ENTRY() \
45         tdm_private_display *private_display; \
46         tdm_private_output *private_output; \
47         tdm_private_layer *private_layer; \
48         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
49         TDM_RETURN_VAL_IF_FAIL(layer != NULL, TDM_ERROR_INVALID_PARAMETER); \
50         private_layer = (tdm_private_layer*)layer; \
51         private_output = private_layer->private_output; \
52         private_display = private_output->private_display
53
54 #define LAYER_FUNC_ENTRY_ERROR() \
55         tdm_private_display *private_display; \
56         tdm_private_output *private_output; \
57         tdm_private_layer *private_layer; \
58         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
59         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(layer != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
60         private_layer = (tdm_private_layer*)layer; \
61         private_output = private_layer->private_output; \
62         private_display = private_output->private_display
63
64 #define LAYER_FUNC_ENTRY_VOID_RETURN() \
65         tdm_private_display *private_display; \
66         tdm_private_output *private_output; \
67         tdm_private_layer *private_layer; \
68         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
69         TDM_RETURN_IF_FAIL(layer != NULL); \
70         private_layer = (tdm_private_layer*)layer; \
71         private_output = private_layer->private_output; \
72         private_display = private_output->private_display
73
74 static void _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer);
75 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
76                                                                           unsigned int tv_sec, unsigned int tv_usec, void *user_data);
77 static void _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data);
78 static void _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data);
79 static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
80                                                                                 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
81 static void _tdm_layer_reset_pending_data(tdm_private_layer *private_layer);
82
83 EXTERN tdm_error
84 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
85 {
86         LAYER_FUNC_ENTRY();
87
88         TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
89
90         _pthread_mutex_lock(&private_display->lock);
91
92         *capabilities = private_layer->caps.capabilities;
93
94         _pthread_mutex_unlock(&private_display->lock);
95
96         return ret;
97 }
98
99 EXTERN tdm_error
100 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
101 {
102         LAYER_FUNC_ENTRY();
103
104         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
105         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
106
107         _pthread_mutex_lock(&private_display->lock);
108
109         *formats = (const tbm_format *)private_layer->caps.formats;
110         *count = private_layer->caps.format_count;
111
112         _pthread_mutex_unlock(&private_display->lock);
113
114         return ret;
115 }
116
117 EXTERN tdm_error
118 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
119 {
120         LAYER_FUNC_ENTRY();
121
122         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
123         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
124
125         _pthread_mutex_lock(&private_display->lock);
126
127         *props = (const tdm_prop *)private_layer->caps.props;
128         *count = private_layer->caps.prop_count;
129
130         _pthread_mutex_unlock(&private_display->lock);
131
132         return ret;
133 }
134
135 EXTERN tdm_error
136 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
137 {
138         LAYER_FUNC_ENTRY();
139
140         TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
141
142         _pthread_mutex_lock(&private_display->lock);
143
144         *zpos = private_layer->caps.zpos;
145
146         _pthread_mutex_unlock(&private_display->lock);
147
148         return ret;
149 }
150
151 EXTERN tdm_error
152 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
153 {
154         tdm_func_layer *func_layer;
155         LAYER_FUNC_ENTRY();
156
157         _pthread_mutex_lock(&private_display->lock);
158
159         func_layer = &private_display->func_layer;
160
161         if (private_layer->usable)
162                 TDM_INFO("layer(%d) not usable", private_layer->index);
163
164         private_layer->usable = 0;
165
166         if (!func_layer->layer_set_property) {
167                 /* LCOV_EXCL_START */
168                 _pthread_mutex_unlock(&private_display->lock);
169                 TDM_ERR("not implemented!!");
170                 return TDM_ERROR_NOT_IMPLEMENTED;
171                 /* LCOV_EXCL_STOP */
172         }
173
174         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
175
176         _pthread_mutex_unlock(&private_display->lock);
177
178         return ret;
179 }
180
181 EXTERN tdm_error
182 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
183 {
184         tdm_func_layer *func_layer;
185         LAYER_FUNC_ENTRY();
186
187         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
188
189         _pthread_mutex_lock(&private_display->lock);
190
191         func_layer = &private_display->func_layer;
192
193         if (!func_layer->layer_get_property) {
194                 /* LCOV_EXCL_START */
195                 _pthread_mutex_unlock(&private_display->lock);
196                 TDM_ERR("not implemented!!");
197                 return TDM_ERROR_NOT_IMPLEMENTED;
198                 /* LCOV_EXCL_SOP */
199         }
200
201         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
202
203         _pthread_mutex_unlock(&private_display->lock);
204
205         return ret;
206 }
207
208 INTERN tdm_error
209 tdm_layer_set_info_internal(tdm_private_layer *private_layer, tdm_info_layer *info)
210 {
211         tdm_private_output *private_output = private_layer->private_output;
212         tdm_private_display *private_display = private_output->private_display;
213         tdm_func_layer *func_layer;
214         char fmtstr[128];
215
216         func_layer = &private_display->func_layer;
217
218         if (private_layer->usable)
219                 TDM_INFO("layer(%p) not usable", private_layer);
220
221         private_layer->usable = 0;
222
223         if (!func_layer->layer_set_info) {
224                 /* LCOV_EXCL_START */
225                 TDM_ERR("not implemented!!");
226                 return TDM_ERROR_NOT_IMPLEMENTED;
227                 /* LCOV_EXCL_STOP */
228         }
229
230         if (info->src_config.format)
231                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
232         else
233                 snprintf(fmtstr, 128, "NONE");
234
235         TDM_INFO("layer(%p) info: src(%ux%u %u,%u %ux%u %s) dst(%u,%u %ux%u) trans(%d)",
236                          private_layer, info->src_config.size.h, info->src_config.size.v,
237                          info->src_config.pos.x, info->src_config.pos.y,
238                          info->src_config.pos.w, info->src_config.pos.h,
239                          fmtstr,
240                          info->dst_pos.x, info->dst_pos.y,
241                          info->dst_pos.w, info->dst_pos.h,
242                          info->transform);
243
244         private_layer->pending_info_changed = 1;
245         private_layer->pending_info = *info;
246
247         return TDM_ERROR_NONE;
248 }
249
250 EXTERN tdm_error
251 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
252 {
253         LAYER_FUNC_ENTRY();
254
255         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
256
257         _pthread_mutex_lock(&private_display->lock);
258
259         ret = tdm_layer_set_info_internal(private_layer, info);
260
261         _pthread_mutex_unlock(&private_display->lock);
262
263         return ret;
264 }
265
266 EXTERN tdm_error
267 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
268 {
269         tdm_func_layer *func_layer;
270         LAYER_FUNC_ENTRY();
271
272         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
273
274         _pthread_mutex_lock(&private_display->lock);
275
276         func_layer = &private_display->func_layer;
277
278         if (!func_layer->layer_get_info) {
279                 /* LCOV_EXCL_START */
280                 _pthread_mutex_unlock(&private_display->lock);
281                 TDM_ERR("not implemented!!");
282                 return TDM_ERROR_NOT_IMPLEMENTED;
283                 /* LCOV_EXCL_STOP */
284         }
285
286         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
287
288         _pthread_mutex_unlock(&private_display->lock);
289
290         return ret;
291 }
292
293 /* LCOV_EXCL_START */
294 static void
295 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
296 {
297         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
298         tdm_private_output *private_output = private_layer->private_output;
299         unsigned int pipe;
300         char fname[TDM_PATH_LEN], bufs[TDM_PATH_LEN];
301         int zpos, len = TDM_PATH_LEN;
302         tdm_private_layer *l = NULL;
303         char *p = bufs;
304         int *remain = &len;
305
306         pipe = private_output->pipe;
307         zpos = private_layer->caps.zpos;
308
309         bufs[0] = '\0';
310         LIST_FOR_EACH_ENTRY(l, &private_output->layer_list, link) {
311                 if (!l->showing_buffer)
312                         continue;
313                 TDM_SNPRINTF(p, remain, "_%p", l->showing_buffer->buffer);
314         }
315
316         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d%s", pipe, zpos, bufs);
317
318         tbm_surface_internal_dump_buffer(buffer, fname);
319         TDM_DBG("%s dump excute", fname);
320
321         return;
322 }
323 /* LCOV_EXCL_STOP */
324
325 static void
326 _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer)
327 {
328         tdm_private_display *private_display;
329
330         if (!layer_buffer)
331                 return;
332
333         private_display = private_layer->private_output->private_display;
334
335         LIST_DEL(&layer_buffer->link);
336         if (layer_buffer->buffer) {
337                 _pthread_mutex_unlock(&private_display->lock);
338                 tdm_buffer_unref_backend(layer_buffer->buffer);
339                 if (private_layer->buffer_queue)
340                         tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer);
341                 _pthread_mutex_lock(&private_display->lock);
342         }
343         free(layer_buffer);
344 }
345
346 static void
347 _tdm_layer_free_all_buffers(tdm_private_layer *private_layer)
348 {
349         tdm_private_output *private_output = private_layer->private_output;
350         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
351         struct list_head clone_list;
352
353         LIST_INITHEAD(&clone_list);
354
355         _tdm_layer_reset_pending_data(private_layer);
356
357         if (private_layer->waiting_buffer) {
358                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
359                 private_layer->waiting_buffer = NULL;
360
361                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
362                         TDM_INFO("layer(%p) waiting_buffer(%p)",
363                                          private_layer, private_layer->waiting_buffer);
364         }
365
366         if (private_layer->committed_buffer) {
367                 _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
368                 private_layer->committed_buffer = NULL;
369
370                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
371                         TDM_INFO("layer(%p) committed_buffer(%p)",
372                                          private_layer, private_layer->committed_buffer);
373         }
374
375         if (private_layer->showing_buffer) {
376                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
377                 private_layer->showing_buffer = NULL;
378
379                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
380                         TDM_INFO("layer(%p) showing_buffer(%p)",
381                                          private_layer, private_layer->showing_buffer);
382         }
383
384         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
385                 if (lm->private_layer != private_layer)
386                         continue;
387                 LIST_DEL(&lm->link);
388                 LIST_ADDTAIL(&lm->link, &clone_list);
389         }
390
391         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
392                 LIST_DEL(&lm->link);
393                 tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
394                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
395                 free(lm);
396         }
397
398         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
399                 if (lm->private_layer != private_layer)
400                         continue;
401                 LIST_DEL(&lm->link);
402                 LIST_ADDTAIL(&lm->link, &clone_list);
403         }
404
405         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
406                 LIST_DEL(&lm->link);
407                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
408                 free(lm);
409         }
410
411         if (private_layer->buffer_queue) {
412                 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer);
413                 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer);
414                 private_layer->buffer_queue = NULL;
415         }
416 }
417
418 INTERN tdm_error
419 tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h buffer)
420 {
421         tdm_private_output *private_output = private_layer->private_output;
422         tdm_private_display *private_display = private_output->private_display;
423         tdm_func_layer *func_layer;
424
425         /* LCOV_EXCL_START */
426         /* dump buffer */
427         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
428                 _tdm_layer_dump_buffer(private_layer, buffer);
429
430         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
431                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
432                 char str[TDM_PATH_LEN];
433                 static int i;
434                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
435                                  private_output->index, private_layer->index, i++);
436                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
437         }
438         /* LCOV_EXCL_STOP */
439
440         func_layer = &private_display->func_layer;
441
442         if (private_layer->usable)
443                 TDM_INFO("layer(%p) not usable", private_layer);
444
445         private_layer->usable = 0;
446
447         if (!func_layer->layer_set_buffer) {
448                 /* LCOV_EXCL_START */
449                 TDM_ERR("not implemented!!");
450                 return TDM_ERROR_NOT_IMPLEMENTED;
451                 /* LCOV_EXCL_START */
452         }
453
454         private_layer->pending_buffer_changed = 1;
455
456         if (private_layer->pending_buffer) {
457
458                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
459                         TDM_INFO("layer(%p) pending_buffer(%p) skipped",
460                                          private_layer, private_layer->pending_buffer);
461
462                 if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
463                         tbm_bo bo = tbm_surface_internal_get_bo(private_layer->pending_buffer, 0);
464                         TDM_TRACE_ASYNC_END((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
465                 }
466
467                 tbm_surface_internal_unref(private_layer->pending_buffer);
468         }
469
470         tbm_surface_internal_ref(buffer);
471         private_layer->pending_buffer = buffer;
472
473         if (tdm_debug_module & TDM_DEBUG_BUFFER)
474                 TDM_INFO("layer(%p) pending_buffer(%p)",
475                                  private_layer, private_layer->pending_buffer);
476
477         if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
478                 tbm_bo bo = tbm_surface_internal_get_bo(private_layer->pending_buffer, 0);
479                 TDM_TRACE_ASYNC_BEGIN((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
480         }
481
482         return TDM_ERROR_NONE;
483 }
484
485 EXTERN tdm_error
486 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
487 {
488         LAYER_FUNC_ENTRY();
489
490         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
491
492         _pthread_mutex_lock(&private_display->lock);
493
494         ret = tdm_layer_set_buffer_internal(private_layer, buffer);
495
496         _pthread_mutex_unlock(&private_display->lock);
497
498         return ret;
499 }
500
501 INTERN tdm_error
502 tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer)
503 {
504         tdm_private_output *private_output = private_layer->private_output;
505         tdm_private_display *private_display = private_output->private_display;
506         tdm_func_layer *func_layer;
507         tdm_error ret = TDM_ERROR_NONE;
508
509         func_layer = &private_display->func_layer;
510
511         _tdm_layer_free_all_buffers(private_layer);
512
513         private_layer->usable = 1;
514
515         if (private_layer->usable)
516                 TDM_INFO("layer(%p) now usable", private_layer);
517
518         if (!func_layer->layer_unset_buffer) {
519                 /* LCOV_EXCL_START */
520                 TDM_ERR("not implemented!!");
521                 return TDM_ERROR_NOT_IMPLEMENTED;
522                 /* LCOV_EXCL_START */
523         }
524
525         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
526         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
527
528         return ret;
529 }
530
531 EXTERN tdm_error
532 tdm_layer_unset_buffer(tdm_layer *layer)
533 {
534         LAYER_FUNC_ENTRY();
535
536         _pthread_mutex_lock(&private_display->lock);
537
538         ret = tdm_layer_unset_buffer_internal(private_layer);
539
540         _pthread_mutex_unlock(&private_display->lock);
541
542         return ret;
543 }
544
545 INTERN void
546 tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
547 {
548         tdm_private_output *private_output = private_layer->private_output;
549         tdm_private_display *private_display = private_output->private_display;
550
551         /* LCOV_EXCL_START */
552         if (private_display->print_fps) {
553                 double curr = tdm_helper_get_time();
554                 if (private_layer->fps_stamp == 0) {
555                         private_layer->fps_stamp = curr;
556                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
557                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
558                         private_layer->fps_count = 0;
559                         private_layer->fps_stamp = curr;
560                 } else
561                         private_layer->fps_count++;
562         } else if (private_layer->fps_stamp != 0) {
563                 private_layer->fps_stamp = 0;
564                 private_layer->fps_count = 0;
565         }
566         /* LCOV_EXCL_STOP */
567
568         if (private_layer->showing_buffer) {
569                 if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
570                         tbm_bo bo = tbm_surface_internal_get_bo(private_layer->showing_buffer->buffer, 0);
571                         TDM_TRACE_ASYNC_END((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
572                 }
573
574                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
575         }
576
577         private_layer->showing_buffer = *committed_buffer;
578         *committed_buffer = NULL;
579
580         if (tdm_debug_module & TDM_DEBUG_BUFFER)
581                 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
582                                  private_layer, *committed_buffer,
583                                  (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
584 }
585
586 static void
587 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
588                                                          unsigned int tv_sec, unsigned int tv_usec)
589 {
590         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
591         tdm_private_display *private_display;
592         struct list_head clone_list, pending_clone_list;
593         tdm_error ret = TDM_ERROR_NONE;
594
595         private_display = private_output->private_display;
596
597         private_output->layer_waiting_vblank = 0;
598
599         LIST_INITHEAD(&clone_list);
600         LIST_INITHEAD(&pending_clone_list);
601
602         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
603                 LIST_DEL(&lm->link);
604                 lm->private_layer->committing = 0;
605                 LIST_ADDTAIL(&lm->link, &clone_list);
606         }
607
608         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
609                 LIST_DEL(&lm->link);
610                 lm->private_layer->committing = 0;
611                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
612         }
613
614         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
615                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
616                         TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
617                                          lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
618
619                 LIST_DEL(&lm->link);
620                 tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
621                 _pthread_mutex_unlock(&private_display->lock);
622                 if (lm->func)
623                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
624                 _pthread_mutex_lock(&private_display->lock);
625                 if (lm->committed_buffer)
626                         _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
627                 free(lm);
628         }
629
630         if (LIST_IS_EMPTY(&pending_clone_list))
631                 return;
632
633         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
634
635         ret = tdm_output_commit_internal(private_output, 0, NULL, NULL);
636         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
637
638         if (tdm_debug_module & TDM_DEBUG_COMMIT)
639                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
640
641         if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
642                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
643                 if (!private_output->layer_waiting_vblank) {
644                         _pthread_mutex_unlock(&private_display->lock);
645                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
646                         _pthread_mutex_lock(&private_display->lock);
647                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
648                         private_output->layer_waiting_vblank = 1;
649                 }
650         }
651
652         if (tdm_debug_module & TDM_DEBUG_COMMIT)
653                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
654
655         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
656                 LIST_DEL(&lm->link);
657                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
658         }
659
660         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
661                 TDM_WRN("dpms %s. Directly call vblank callback.", tdm_dpms_str(private_output->current_dpms_value));
662                 _pthread_mutex_unlock(&private_display->lock);
663                 _tdm_layer_cb_wait_vblank(private_output->vblank, 0, 0, 0, 0, private_output);
664                 _pthread_mutex_lock(&private_display->lock);
665         }
666
667         return;
668 wait_failed:
669         /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
670          * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
671          * the layer commit handler MUST be called.
672          */
673         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
674                 TDM_WRN("Directly call layer commit handlers: ret(%d)\n", ret);
675                 LIST_DEL(&lm->link);
676                 _pthread_mutex_unlock(&private_display->lock);
677                 if (lm->func)
678                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
679                 _pthread_mutex_lock(&private_display->lock);
680                 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
681                 free(lm);
682         }
683
684         return;
685 }
686
687 static void
688 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
689                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
690 {
691         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
692         tdm_private_layer_commit_handler *lm = NULL;
693         tdm_private_display *private_display;
694         tdm_private_output *private_output = output;
695         tdm_private_layer *private_layer;
696         int found = 0;
697
698         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
699
700         private_display = private_output->private_display;
701
702         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
703                 if (layer_commit_handler == lm) {
704                         found = 1;
705                         break;
706                 }
707         }
708
709         if (!found)
710                 return;
711
712         LIST_DEL(&layer_commit_handler->link);
713
714         private_layer = layer_commit_handler->private_layer;
715
716         if (tdm_debug_module & TDM_DEBUG_COMMIT)
717                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
718                                  private_layer, private_output->pipe, layer_commit_handler);
719
720         _pthread_mutex_lock(&private_display->lock);
721
722         tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
723
724         if (layer_commit_handler->func) {
725                 _pthread_mutex_unlock(&private_display->lock);
726                 layer_commit_handler->func(private_output, sequence,
727                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
728                 _pthread_mutex_lock(&private_display->lock);
729         }
730
731         free(layer_commit_handler);
732
733         _pthread_mutex_unlock(&private_display->lock);
734 }
735
736 static void
737 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
738                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
739 {
740         tdm_private_output *private_output = user_data;
741         tdm_private_display *private_display;
742
743         TDM_RETURN_IF_FAIL(private_output != NULL);
744
745         private_display = private_output->private_display;
746
747         _pthread_mutex_lock(&private_display->lock);
748
749         if (tdm_debug_module & TDM_DEBUG_COMMIT)
750                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
751
752         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
753
754         _pthread_mutex_unlock(&private_display->lock);
755 }
756
757 static unsigned int
758 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
759 {
760         tdm_private_layer *private_layer = NULL;
761         unsigned int count = 0;
762
763         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
764                 if (!private_layer->usable)
765                         count++;
766         }
767
768         return count;
769 }
770
771 /* commit_per_vblank == 1: we can commit if
772  *                           - there is no previous commit request
773  *                           - only 1 layer is used
774  * commit_per_vblank == 2: we can commit if
775  *                           - there is no previous commit request
776  */
777 static int
778 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
779 {
780         tdm_private_output *private_output = private_layer->private_output;
781
782         TDM_RETURN_VAL_IF_FAIL(private_output->commit_per_vblank > 0, 1);
783
784         /* There is a previous commit request which is not done and displayed on screen yet.
785          * We can't commit at this time.
786          */
787         if (!LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
788                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
789                         TDM_INFO("layer(%p) commit: not possible(previous commit)", private_layer);
790                 return 0;
791         }
792
793         if (private_output->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) {
794                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
795                         TDM_INFO("layer(%p) commit: not possible(more than 2 layers)", private_layer);
796                 return 0;
797         }
798
799         if (tdm_debug_module & TDM_DEBUG_COMMIT)
800                 TDM_INFO("layer(%p) commit: possible", private_layer);
801
802         return 1;
803 }
804
805 static void
806 _tdm_layer_reset_pending_data(tdm_private_layer *private_layer)
807 {
808         private_layer->pending_info_changed = 0;
809         memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info);
810
811         private_layer->pending_buffer_changed = 0;
812         if (private_layer->pending_buffer) {
813                 tbm_surface_internal_unref(private_layer->pending_buffer);
814                 private_layer->pending_buffer = NULL;
815         }
816 }
817
818 INTERN tdm_error
819 tdm_layer_commit_pending_data(tdm_private_layer *private_layer)
820 {
821         tdm_private_output *private_output = private_layer->private_output;
822         tdm_private_display *private_display = private_output->private_display;
823         tdm_func_layer *func_layer;
824         tdm_error ret = TDM_ERROR_NONE;
825
826         func_layer = &private_display->func_layer;
827
828         if (private_layer->pending_info_changed) {
829                 ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info);
830                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
831         }
832
833         if (private_layer->pending_buffer_changed) {
834                 tdm_private_layer_buffer *layer_buffer;
835
836                 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
837                 TDM_GOTO_IF_FAIL(layer_buffer != NULL, done);
838
839                 LIST_INITHEAD(&layer_buffer->link);
840
841                 ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer);
842                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
843
844                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
845                         TDM_INFO("layer(%p) pending_buffer(%p) committed",
846                                          private_layer, private_layer->pending_buffer);
847
848                 if (ret == TDM_ERROR_NONE) {
849                         if (private_layer->waiting_buffer)
850                                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
851
852                         private_layer->waiting_buffer = layer_buffer;
853                         private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer);
854                         if (tdm_debug_module & TDM_DEBUG_BUFFER)
855                                 TDM_INFO("layer(%p) waiting_buffer(%p)",
856                                                  private_layer, private_layer->waiting_buffer->buffer);
857                 } else
858                         _tdm_layer_free_buffer(private_layer, layer_buffer);
859         }
860
861 done:
862         _tdm_layer_reset_pending_data(private_layer);
863
864         return ret;
865 }
866
867 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
868  * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
869  * the layer commit handler MUST be called.
870  */
871 static tdm_error
872 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
873 {
874         tdm_private_layer_commit_handler *layer_commit_handler;
875         LAYER_FUNC_ENTRY();
876
877         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
878         if (!layer_commit_handler) {
879                 /* LCOV_EXCL_START */
880                 TDM_ERR("failed: alloc memory");
881                 return TDM_ERROR_OUT_OF_MEMORY;
882                 /* LCOV_EXCL_STOP */
883         }
884
885         if (tdm_debug_module & TDM_DEBUG_COMMIT)
886                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
887
888         LIST_INITHEAD(&layer_commit_handler->link);
889         layer_commit_handler->private_layer = private_layer;
890         layer_commit_handler->func = func;
891         layer_commit_handler->user_data = user_data;
892
893         layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
894         private_layer->waiting_buffer = NULL;
895
896         if (tdm_debug_module & TDM_DEBUG_BUFFER)
897                 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
898                                  private_layer, private_layer->waiting_buffer,
899                                  (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
900
901         if (!private_output->commit_per_vblank) {
902                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
903
904                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
905                 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
906                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
907
908                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
909                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
910         } else {
911                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
912
913                 if (private_layer->committing)
914                         TDM_WRN("layer(%d) too many commit", private_layer->index);
915                 else
916                         private_layer->committing = 1;
917
918                 if (_tdm_layer_commit_possible(private_layer)) {
919                         /* add to layer_commit_handler_list */
920                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
921                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
922                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
923
924                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
925                                 TDM_INFO("layer(%p) commit: output", private_layer);
926                 } else {
927                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
928                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
929
930                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
931                                 TDM_INFO("layer(%p) commit: pending", private_layer);
932                 }
933
934                 if (!private_output->vblank) {
935                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
936                         _pthread_mutex_unlock(&private_display->lock);
937                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
938                         _pthread_mutex_lock(&private_display->lock);
939                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
940                 }
941
942                 if (!private_output->layer_waiting_vblank) {
943                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
944                         _pthread_mutex_unlock(&private_display->lock);
945                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
946                         _pthread_mutex_lock(&private_display->lock);
947                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
948                         private_output->layer_waiting_vblank = 1;
949
950                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
951                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
952                 }
953         }
954
955         return ret;
956
957 commit_failed:
958         if (layer_commit_handler) {
959                 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
960                 LIST_DEL(&layer_commit_handler->link);
961                 free(layer_commit_handler);
962         }
963         return ret;
964 }
965
966 INTERN tdm_error
967 tdm_layer_commit_internal(tdm_private_layer *private_layer, tdm_layer_commit_handler func, void *user_data)
968 {
969         tdm_private_output *private_output = private_layer->private_output;
970         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */
971
972         if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) {
973                 if (!private_output->commit_per_vblank)
974                         private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT;
975                 else
976                         private_output->commit_type = TDM_COMMIT_TYPE_LAYER;
977         }
978
979         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
980                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", private_layer, private_output->pipe,
981                                 tdm_dpms_str(private_output->current_dpms_value));
982                 return TDM_ERROR_DPMS_OFF;
983         }
984
985         /* don't call this inside of _tdm_layer_commit */
986         ret = tdm_layer_commit_pending_data(private_layer);
987         if (ret != TDM_ERROR_NONE) {
988                 TDM_ERR("layer(%p) committing pending data failed", private_layer);
989                 return ret;
990         }
991
992         ret = _tdm_layer_commit(private_layer, func, user_data);
993
994         return ret;
995 }
996
997 EXTERN tdm_error
998 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
999 {
1000         LAYER_FUNC_ENTRY();
1001
1002         _pthread_mutex_lock(&private_display->lock);
1003
1004         ret = tdm_layer_commit_internal(private_layer, func, user_data);
1005
1006         _pthread_mutex_unlock(&private_display->lock);
1007
1008         return ret;
1009 }
1010
1011 EXTERN tdm_error
1012 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
1013 {
1014         LAYER_FUNC_ENTRY();
1015
1016         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
1017
1018         _pthread_mutex_lock(&private_display->lock);
1019
1020         *committing = private_layer->committing;
1021
1022         _pthread_mutex_unlock(&private_display->lock);
1023
1024         return ret;
1025 }
1026
1027 INTERN void
1028 tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1029 {
1030         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1031         tdm_private_output *private_output = private_layer->private_output;
1032         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1033
1034         TDM_RETURN_IF_FAIL(private_layer != NULL);
1035         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1036
1037         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1038                 if (lm->func == func && lm->user_data == user_data) {
1039                         LIST_DEL(&lm->link);
1040                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1041                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1042                         free(lm);
1043                         break;
1044                 }
1045         }
1046
1047         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1048                 if (lm->func == func && lm->user_data == user_data) {
1049                         LIST_DEL(&lm->link);
1050                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1051                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1052                         free(lm);
1053                         break;
1054                 }
1055         }
1056 }
1057
1058 EXTERN tdm_error
1059 tdm_layer_remove_commit_handler(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1060 {
1061         LAYER_FUNC_ENTRY();
1062
1063         _pthread_mutex_lock(&private_display->lock);
1064
1065         tdm_layer_remove_commit_handler_internal(layer, func, user_data);
1066
1067         _pthread_mutex_unlock(&private_display->lock);
1068
1069         return ret;
1070 }
1071
1072 EXTERN tbm_surface_h
1073 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1074 {
1075         tbm_surface_h buffer;
1076         LAYER_FUNC_ENTRY_ERROR();
1077
1078         _pthread_mutex_lock(&private_display->lock);
1079
1080         if (error)
1081                 *error = TDM_ERROR_NONE;
1082
1083         if (private_layer->showing_buffer) {
1084                 buffer = private_layer->showing_buffer->buffer;
1085         } else {
1086                 if (error)
1087                         *error = TDM_ERROR_OPERATION_FAILED;
1088                 _pthread_mutex_unlock(&private_display->lock);
1089                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1090                 return NULL;
1091         }
1092         _pthread_mutex_unlock(&private_display->lock);
1093
1094         return buffer;
1095 }
1096
1097 static void
1098 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1099 {
1100         TDM_RETURN_IF_FAIL(data != NULL);
1101         tdm_layer *layer = data;
1102         tdm_func_layer *func_layer;
1103         tbm_surface_h surface = NULL;
1104         tdm_private_layer_buffer *layer_buffer;
1105         LAYER_FUNC_ENTRY_VOID_RETURN();
1106
1107         _pthread_mutex_lock(&private_display->lock);
1108
1109         func_layer = &private_display->func_layer;
1110         if (!func_layer->layer_set_buffer) {
1111                 /* LCOV_EXCL_START */
1112                 _pthread_mutex_unlock(&private_display->lock);
1113                 return;
1114                 /* LCOV_EXCL_STOP */
1115         }
1116
1117         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
1118         if (!layer_buffer) {
1119                 /* LCOV_EXCL_START */
1120                 _pthread_mutex_unlock(&private_display->lock);
1121                 TDM_ERR("alloc failed");
1122                 return;
1123                 /* LCOV_EXCL_STOP */
1124         }
1125         LIST_INITHEAD(&layer_buffer->link);
1126
1127         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1128                 surface == NULL) {
1129                 /* LCOV_EXCL_START */
1130                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1131                                 private_layer, surface);
1132                 _pthread_mutex_unlock(&private_display->lock);
1133                 free(layer_buffer);
1134                 return;
1135                 /* LCOV_EXCL_STOP */
1136         }
1137
1138         /* we don't need to handle pending data here because the changes in this function
1139          * should be applied immediately. we can't expect calling tdm_layer_commit.
1140          */
1141         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1142         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1143
1144         if (ret == TDM_ERROR_NONE) {
1145                 if (private_layer->waiting_buffer) {
1146                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
1147                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1148                 }
1149
1150                 private_layer->waiting_buffer = layer_buffer;
1151                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
1152
1153                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1154                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1155                                          private_layer, private_layer->waiting_buffer->buffer);
1156
1157                 if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1158                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
1159                         if (ret != TDM_ERROR_NONE)
1160                                 TDM_ERR("tdm_output_commit_internal() is fail");
1161                 } else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) {
1162                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
1163                         if (ret != TDM_ERROR_NONE)
1164                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
1165                 } else {
1166                         TDM_NEVER_GET_HERE();
1167                 }
1168         } else
1169                 _tdm_layer_free_buffer(private_layer, layer_buffer);
1170
1171         _pthread_mutex_unlock(&private_display->lock);
1172 }
1173
1174 static void
1175 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1176 {
1177         TDM_RETURN_IF_FAIL(data != NULL);
1178         tdm_layer *layer = data;
1179         LAYER_FUNC_ENTRY_VOID_RETURN();
1180         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1181
1182         _pthread_mutex_lock(&private_display->lock);
1183
1184         private_layer->buffer_queue = NULL;
1185
1186         _tdm_layer_free_all_buffers(private_layer);
1187
1188         _pthread_mutex_unlock(&private_display->lock);
1189 }
1190
1191 EXTERN tdm_error
1192 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1193 {
1194         tdm_func_layer *func_layer;
1195         LAYER_FUNC_ENTRY();
1196
1197         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1198
1199         _pthread_mutex_lock(&private_display->lock);
1200
1201         func_layer = &private_display->func_layer;
1202
1203         if (private_layer->usable)
1204                 TDM_INFO("layer(%p) not usable", private_layer);
1205
1206         private_layer->usable = 0;
1207
1208         if (!func_layer->layer_set_buffer) {
1209                 /* LCOV_EXCL_START */
1210                 _pthread_mutex_unlock(&private_display->lock);
1211                 TDM_ERR("not implemented!!");
1212                 return TDM_ERROR_NOT_IMPLEMENTED;
1213                 /* LCOV_EXCL_STOP */
1214         }
1215
1216         if (buffer_queue == private_layer->buffer_queue) {
1217                 _pthread_mutex_unlock(&private_display->lock);
1218                 return TDM_ERROR_NONE;
1219         }
1220
1221         if (private_layer->waiting_buffer) {
1222                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1223                 private_layer->waiting_buffer = NULL;
1224
1225                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1226                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1227                                          private_layer, private_layer->waiting_buffer);
1228         }
1229
1230         private_layer->buffer_queue = buffer_queue;
1231         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1232                                                                                 _tbm_layer_queue_acquirable_cb,
1233                                                                                 private_layer);
1234         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1235                                                                          _tbm_layer_queue_destroy_cb,
1236                                                                          private_layer);
1237         _pthread_mutex_unlock(&private_display->lock);
1238
1239         return ret;
1240 }
1241
1242 EXTERN tdm_error
1243 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1244 {
1245         return tdm_layer_unset_buffer(layer);
1246 }
1247
1248 EXTERN tdm_error
1249 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1250 {
1251         LAYER_FUNC_ENTRY();
1252
1253         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1254
1255         _pthread_mutex_lock(&private_display->lock);
1256
1257         *usable = private_layer->usable;
1258
1259         _pthread_mutex_unlock(&private_display->lock);
1260
1261         return ret;
1262 }
1263
1264 EXTERN tdm_error
1265 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1266 {
1267         tdm_func_layer *func_layer;
1268         LAYER_FUNC_ENTRY();
1269
1270         _pthread_mutex_lock(&private_display->lock);
1271
1272         func_layer = &private_display->func_layer;
1273
1274         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1275                 TDM_ERR("layer(%p) is not video layer", private_layer);
1276                 _pthread_mutex_unlock(&private_display->lock);
1277                 return TDM_ERROR_INVALID_PARAMETER;
1278         }
1279
1280         if (!func_layer->layer_set_video_pos) {
1281                 /* LCOV_EXCL_START */
1282                 _pthread_mutex_unlock(&private_display->lock);
1283                 TDM_ERR("not implemented!!");
1284                 return TDM_ERROR_NOT_IMPLEMENTED;
1285                 /* LCOV_EXCL_STOP */
1286         }
1287
1288         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1289
1290         _pthread_mutex_unlock(&private_display->lock);
1291
1292         return ret;
1293 }
1294
1295 EXTERN tdm_capture *
1296 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1297 {
1298         tdm_capture *capture = NULL;
1299
1300         LAYER_FUNC_ENTRY_ERROR();
1301
1302         _pthread_mutex_lock(&private_display->lock);
1303
1304         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1305
1306         _pthread_mutex_unlock(&private_display->lock);
1307
1308         return capture;
1309 }
1310
1311 EXTERN tdm_error
1312 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1313 {
1314         tdm_func_layer *func_layer;
1315         LAYER_FUNC_ENTRY();
1316         TDM_RETURN_VAL_IF_FAIL(flags != NULL, TDM_ERROR_INVALID_PARAMETER);
1317
1318         _pthread_mutex_lock(&private_display->lock);
1319
1320         func_layer = &private_display->func_layer;
1321
1322         if (!func_layer->layer_get_buffer_flags) {
1323                 /* LCOV_EXCL_START */
1324                 _pthread_mutex_unlock(&private_display->lock);
1325                 TDM_ERR("not implemented!!");
1326                 return TDM_ERROR_NOT_IMPLEMENTED;
1327                 /* LCOV_EXCL_STOP */
1328         }
1329
1330         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1331
1332         _pthread_mutex_unlock(&private_display->lock);
1333
1334         return ret;
1335 }