layer: add tdm_layer_set_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 EXTERN tdm_error
502 tdm_layer_unset_buffer(tdm_layer *layer)
503 {
504         tdm_func_layer *func_layer;
505         LAYER_FUNC_ENTRY();
506
507         _pthread_mutex_lock(&private_display->lock);
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                 _pthread_mutex_unlock(&private_display->lock);
521                 TDM_ERR("not implemented!!");
522                 return TDM_ERROR_NOT_IMPLEMENTED;
523                 /* LCOV_EXCL_START */
524         }
525
526         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
527         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
528
529         _pthread_mutex_unlock(&private_display->lock);
530
531         return ret;
532 }
533
534 INTERN void
535 tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
536 {
537         tdm_private_output *private_output = private_layer->private_output;
538         tdm_private_display *private_display = private_output->private_display;
539
540         /* LCOV_EXCL_START */
541         if (private_display->print_fps) {
542                 double curr = tdm_helper_get_time();
543                 if (private_layer->fps_stamp == 0) {
544                         private_layer->fps_stamp = curr;
545                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
546                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
547                         private_layer->fps_count = 0;
548                         private_layer->fps_stamp = curr;
549                 } else
550                         private_layer->fps_count++;
551         } else if (private_layer->fps_stamp != 0) {
552                 private_layer->fps_stamp = 0;
553                 private_layer->fps_count = 0;
554         }
555         /* LCOV_EXCL_STOP */
556
557         if (private_layer->showing_buffer) {
558                 if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
559                         tbm_bo bo = tbm_surface_internal_get_bo(private_layer->showing_buffer->buffer, 0);
560                         TDM_TRACE_ASYNC_END((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
561                 }
562
563                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
564         }
565
566         private_layer->showing_buffer = *committed_buffer;
567         *committed_buffer = NULL;
568
569         if (tdm_debug_module & TDM_DEBUG_BUFFER)
570                 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
571                                  private_layer, *committed_buffer,
572                                  (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
573 }
574
575 static void
576 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
577                                                          unsigned int tv_sec, unsigned int tv_usec)
578 {
579         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
580         tdm_private_display *private_display;
581         struct list_head clone_list, pending_clone_list;
582         tdm_error ret = TDM_ERROR_NONE;
583
584         private_display = private_output->private_display;
585
586         private_output->layer_waiting_vblank = 0;
587
588         LIST_INITHEAD(&clone_list);
589         LIST_INITHEAD(&pending_clone_list);
590
591         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
592                 LIST_DEL(&lm->link);
593                 lm->private_layer->committing = 0;
594                 LIST_ADDTAIL(&lm->link, &clone_list);
595         }
596
597         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
598                 LIST_DEL(&lm->link);
599                 lm->private_layer->committing = 0;
600                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
601         }
602
603         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
604                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
605                         TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
606                                          lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
607
608                 LIST_DEL(&lm->link);
609                 tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
610                 _pthread_mutex_unlock(&private_display->lock);
611                 if (lm->func)
612                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
613                 _pthread_mutex_lock(&private_display->lock);
614                 if (lm->committed_buffer)
615                         _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
616                 free(lm);
617         }
618
619         if (LIST_IS_EMPTY(&pending_clone_list))
620                 return;
621
622         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
623
624         ret = tdm_output_commit_internal(private_output, 0, NULL, NULL);
625         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
626
627         if (tdm_debug_module & TDM_DEBUG_COMMIT)
628                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
629
630         if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
631                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
632                 if (!private_output->layer_waiting_vblank) {
633                         _pthread_mutex_unlock(&private_display->lock);
634                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
635                         _pthread_mutex_lock(&private_display->lock);
636                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
637                         private_output->layer_waiting_vblank = 1;
638                 }
639         }
640
641         if (tdm_debug_module & TDM_DEBUG_COMMIT)
642                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
643
644         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
645                 LIST_DEL(&lm->link);
646                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
647         }
648
649         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
650                 TDM_WRN("dpms %s. Directly call vblank callback.", tdm_dpms_str(private_output->current_dpms_value));
651                 _pthread_mutex_unlock(&private_display->lock);
652                 _tdm_layer_cb_wait_vblank(private_output->vblank, 0, 0, 0, 0, private_output);
653                 _pthread_mutex_lock(&private_display->lock);
654         }
655
656         return;
657 wait_failed:
658         /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
659          * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
660          * the layer commit handler MUST be called.
661          */
662         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
663                 TDM_WRN("Directly call layer commit handlers: ret(%d)\n", ret);
664                 LIST_DEL(&lm->link);
665                 _pthread_mutex_unlock(&private_display->lock);
666                 if (lm->func)
667                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
668                 _pthread_mutex_lock(&private_display->lock);
669                 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
670                 free(lm);
671         }
672
673         return;
674 }
675
676 static void
677 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
678                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
679 {
680         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
681         tdm_private_layer_commit_handler *lm = NULL;
682         tdm_private_display *private_display;
683         tdm_private_output *private_output = output;
684         tdm_private_layer *private_layer;
685         int found = 0;
686
687         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
688
689         private_display = private_output->private_display;
690
691         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
692                 if (layer_commit_handler == lm) {
693                         found = 1;
694                         break;
695                 }
696         }
697
698         if (!found)
699                 return;
700
701         LIST_DEL(&layer_commit_handler->link);
702
703         private_layer = layer_commit_handler->private_layer;
704
705         if (tdm_debug_module & TDM_DEBUG_COMMIT)
706                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
707                                  private_layer, private_output->pipe, layer_commit_handler);
708
709         _pthread_mutex_lock(&private_display->lock);
710
711         tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
712
713         if (layer_commit_handler->func) {
714                 _pthread_mutex_unlock(&private_display->lock);
715                 layer_commit_handler->func(private_output, sequence,
716                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
717                 _pthread_mutex_lock(&private_display->lock);
718         }
719
720         free(layer_commit_handler);
721
722         _pthread_mutex_unlock(&private_display->lock);
723 }
724
725 static void
726 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
727                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
728 {
729         tdm_private_output *private_output = user_data;
730         tdm_private_display *private_display;
731
732         TDM_RETURN_IF_FAIL(private_output != NULL);
733
734         private_display = private_output->private_display;
735
736         _pthread_mutex_lock(&private_display->lock);
737
738         if (tdm_debug_module & TDM_DEBUG_COMMIT)
739                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
740
741         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
742
743         _pthread_mutex_unlock(&private_display->lock);
744 }
745
746 static unsigned int
747 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
748 {
749         tdm_private_layer *private_layer = NULL;
750         unsigned int count = 0;
751
752         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
753                 if (!private_layer->usable)
754                         count++;
755         }
756
757         return count;
758 }
759
760 /* commit_per_vblank == 1: we can commit if
761  *                           - there is no previous commit request
762  *                           - only 1 layer is used
763  * commit_per_vblank == 2: we can commit if
764  *                           - there is no previous commit request
765  */
766 static int
767 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
768 {
769         tdm_private_output *private_output = private_layer->private_output;
770
771         TDM_RETURN_VAL_IF_FAIL(private_output->commit_per_vblank > 0, 1);
772
773         /* There is a previous commit request which is not done and displayed on screen yet.
774          * We can't commit at this time.
775          */
776         if (!LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
777                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
778                         TDM_INFO("layer(%p) commit: not possible(previous commit)", private_layer);
779                 return 0;
780         }
781
782         if (private_output->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) {
783                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
784                         TDM_INFO("layer(%p) commit: not possible(more than 2 layers)", private_layer);
785                 return 0;
786         }
787
788         if (tdm_debug_module & TDM_DEBUG_COMMIT)
789                 TDM_INFO("layer(%p) commit: possible", private_layer);
790
791         return 1;
792 }
793
794 static void
795 _tdm_layer_reset_pending_data(tdm_private_layer *private_layer)
796 {
797         private_layer->pending_info_changed = 0;
798         memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info);
799
800         private_layer->pending_buffer_changed = 0;
801         if (private_layer->pending_buffer) {
802                 tbm_surface_internal_unref(private_layer->pending_buffer);
803                 private_layer->pending_buffer = NULL;
804         }
805 }
806
807 INTERN tdm_error
808 tdm_layer_commit_pending_data(tdm_private_layer *private_layer)
809 {
810         tdm_private_output *private_output = private_layer->private_output;
811         tdm_private_display *private_display = private_output->private_display;
812         tdm_func_layer *func_layer;
813         tdm_error ret = TDM_ERROR_NONE;
814
815         func_layer = &private_display->func_layer;
816
817         if (private_layer->pending_info_changed) {
818                 ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info);
819                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
820         }
821
822         if (private_layer->pending_buffer_changed) {
823                 tdm_private_layer_buffer *layer_buffer;
824
825                 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
826                 TDM_GOTO_IF_FAIL(layer_buffer != NULL, done);
827
828                 LIST_INITHEAD(&layer_buffer->link);
829
830                 ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer);
831                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
832
833                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
834                         TDM_INFO("layer(%p) pending_buffer(%p) committed",
835                                          private_layer, private_layer->pending_buffer);
836
837                 if (ret == TDM_ERROR_NONE) {
838                         if (private_layer->waiting_buffer)
839                                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
840
841                         private_layer->waiting_buffer = layer_buffer;
842                         private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer);
843                         if (tdm_debug_module & TDM_DEBUG_BUFFER)
844                                 TDM_INFO("layer(%p) waiting_buffer(%p)",
845                                                  private_layer, private_layer->waiting_buffer->buffer);
846                 } else
847                         _tdm_layer_free_buffer(private_layer, layer_buffer);
848         }
849
850 done:
851         _tdm_layer_reset_pending_data(private_layer);
852
853         return ret;
854 }
855
856 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
857  * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
858  * the layer commit handler MUST be called.
859  */
860 static tdm_error
861 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
862 {
863         tdm_private_layer_commit_handler *layer_commit_handler;
864         LAYER_FUNC_ENTRY();
865
866         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
867         if (!layer_commit_handler) {
868                 /* LCOV_EXCL_START */
869                 TDM_ERR("failed: alloc memory");
870                 return TDM_ERROR_OUT_OF_MEMORY;
871                 /* LCOV_EXCL_STOP */
872         }
873
874         if (tdm_debug_module & TDM_DEBUG_COMMIT)
875                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
876
877         LIST_INITHEAD(&layer_commit_handler->link);
878         layer_commit_handler->private_layer = private_layer;
879         layer_commit_handler->func = func;
880         layer_commit_handler->user_data = user_data;
881
882         layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
883         private_layer->waiting_buffer = NULL;
884
885         if (tdm_debug_module & TDM_DEBUG_BUFFER)
886                 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
887                                  private_layer, private_layer->waiting_buffer,
888                                  (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
889
890         if (!private_output->commit_per_vblank) {
891                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
892
893                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
894                 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
895                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
896
897                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
898                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
899         } else {
900                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
901
902                 if (private_layer->committing)
903                         TDM_WRN("layer(%d) too many commit", private_layer->index);
904                 else
905                         private_layer->committing = 1;
906
907                 if (_tdm_layer_commit_possible(private_layer)) {
908                         /* add to layer_commit_handler_list */
909                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
910                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
911                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
912
913                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
914                                 TDM_INFO("layer(%p) commit: output", private_layer);
915                 } else {
916                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
917                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
918
919                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
920                                 TDM_INFO("layer(%p) commit: pending", private_layer);
921                 }
922
923                 if (!private_output->vblank) {
924                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
925                         _pthread_mutex_unlock(&private_display->lock);
926                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
927                         _pthread_mutex_lock(&private_display->lock);
928                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
929                 }
930
931                 if (!private_output->layer_waiting_vblank) {
932                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
933                         _pthread_mutex_unlock(&private_display->lock);
934                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
935                         _pthread_mutex_lock(&private_display->lock);
936                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
937                         private_output->layer_waiting_vblank = 1;
938
939                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
940                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
941                 }
942         }
943
944         return ret;
945
946 commit_failed:
947         if (layer_commit_handler) {
948                 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
949                 LIST_DEL(&layer_commit_handler->link);
950                 free(layer_commit_handler);
951         }
952         return ret;
953 }
954
955 INTERN tdm_error
956 tdm_layer_commit_internal(tdm_private_layer *private_layer, tdm_layer_commit_handler func, void *user_data)
957 {
958         tdm_private_output *private_output = private_layer->private_output;
959         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */
960
961         if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) {
962                 if (!private_output->commit_per_vblank)
963                         private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT;
964                 else
965                         private_output->commit_type = TDM_COMMIT_TYPE_LAYER;
966         }
967
968         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
969                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", private_layer, private_output->pipe,
970                                 tdm_dpms_str(private_output->current_dpms_value));
971                 return TDM_ERROR_DPMS_OFF;
972         }
973
974         /* don't call this inside of _tdm_layer_commit */
975         ret = tdm_layer_commit_pending_data(private_layer);
976         if (ret != TDM_ERROR_NONE) {
977                 TDM_ERR("layer(%p) committing pending data failed", private_layer);
978                 return ret;
979         }
980
981         ret = _tdm_layer_commit(private_layer, func, user_data);
982
983         return ret;
984 }
985
986 EXTERN tdm_error
987 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
988 {
989         LAYER_FUNC_ENTRY();
990
991         _pthread_mutex_lock(&private_display->lock);
992
993         ret = tdm_layer_commit_internal(private_layer, func, user_data);
994
995         _pthread_mutex_unlock(&private_display->lock);
996
997         return ret;
998 }
999
1000 EXTERN tdm_error
1001 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
1002 {
1003         LAYER_FUNC_ENTRY();
1004
1005         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
1006
1007         _pthread_mutex_lock(&private_display->lock);
1008
1009         *committing = private_layer->committing;
1010
1011         _pthread_mutex_unlock(&private_display->lock);
1012
1013         return ret;
1014 }
1015
1016 INTERN void
1017 tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1018 {
1019         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1020         tdm_private_output *private_output = private_layer->private_output;
1021         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1022
1023         TDM_RETURN_IF_FAIL(private_layer != NULL);
1024         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1025
1026         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1027                 if (lm->func == func && lm->user_data == user_data) {
1028                         LIST_DEL(&lm->link);
1029                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1030                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1031                         free(lm);
1032                         break;
1033                 }
1034         }
1035
1036         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1037                 if (lm->func == func && lm->user_data == user_data) {
1038                         LIST_DEL(&lm->link);
1039                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1040                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1041                         free(lm);
1042                         break;
1043                 }
1044         }
1045 }
1046
1047 EXTERN tdm_error
1048 tdm_layer_remove_commit_handler(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1049 {
1050         LAYER_FUNC_ENTRY();
1051
1052         _pthread_mutex_lock(&private_display->lock);
1053
1054         tdm_layer_remove_commit_handler_internal(layer, func, user_data);
1055
1056         _pthread_mutex_unlock(&private_display->lock);
1057
1058         return ret;
1059 }
1060
1061 EXTERN tbm_surface_h
1062 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1063 {
1064         tbm_surface_h buffer;
1065         LAYER_FUNC_ENTRY_ERROR();
1066
1067         _pthread_mutex_lock(&private_display->lock);
1068
1069         if (error)
1070                 *error = TDM_ERROR_NONE;
1071
1072         if (private_layer->showing_buffer) {
1073                 buffer = private_layer->showing_buffer->buffer;
1074         } else {
1075                 if (error)
1076                         *error = TDM_ERROR_OPERATION_FAILED;
1077                 _pthread_mutex_unlock(&private_display->lock);
1078                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1079                 return NULL;
1080         }
1081         _pthread_mutex_unlock(&private_display->lock);
1082
1083         return buffer;
1084 }
1085
1086 static void
1087 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1088 {
1089         TDM_RETURN_IF_FAIL(data != NULL);
1090         tdm_layer *layer = data;
1091         tdm_func_layer *func_layer;
1092         tbm_surface_h surface = NULL;
1093         tdm_private_layer_buffer *layer_buffer;
1094         LAYER_FUNC_ENTRY_VOID_RETURN();
1095
1096         _pthread_mutex_lock(&private_display->lock);
1097
1098         func_layer = &private_display->func_layer;
1099         if (!func_layer->layer_set_buffer) {
1100                 /* LCOV_EXCL_START */
1101                 _pthread_mutex_unlock(&private_display->lock);
1102                 return;
1103                 /* LCOV_EXCL_STOP */
1104         }
1105
1106         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
1107         if (!layer_buffer) {
1108                 /* LCOV_EXCL_START */
1109                 _pthread_mutex_unlock(&private_display->lock);
1110                 TDM_ERR("alloc failed");
1111                 return;
1112                 /* LCOV_EXCL_STOP */
1113         }
1114         LIST_INITHEAD(&layer_buffer->link);
1115
1116         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1117                 surface == NULL) {
1118                 /* LCOV_EXCL_START */
1119                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1120                                 private_layer, surface);
1121                 _pthread_mutex_unlock(&private_display->lock);
1122                 free(layer_buffer);
1123                 return;
1124                 /* LCOV_EXCL_STOP */
1125         }
1126
1127         /* we don't need to handle pending data here because the changes in this function
1128          * should be applied immediately. we can't expect calling tdm_layer_commit.
1129          */
1130         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1131         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1132
1133         if (ret == TDM_ERROR_NONE) {
1134                 if (private_layer->waiting_buffer) {
1135                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
1136                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1137                 }
1138
1139                 private_layer->waiting_buffer = layer_buffer;
1140                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
1141
1142                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1143                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1144                                          private_layer, private_layer->waiting_buffer->buffer);
1145
1146                 if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1147                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
1148                         if (ret != TDM_ERROR_NONE)
1149                                 TDM_ERR("tdm_output_commit_internal() is fail");
1150                 } else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) {
1151                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
1152                         if (ret != TDM_ERROR_NONE)
1153                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
1154                 } else {
1155                         TDM_NEVER_GET_HERE();
1156                 }
1157         } else
1158                 _tdm_layer_free_buffer(private_layer, layer_buffer);
1159
1160         _pthread_mutex_unlock(&private_display->lock);
1161 }
1162
1163 static void
1164 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1165 {
1166         TDM_RETURN_IF_FAIL(data != NULL);
1167         tdm_layer *layer = data;
1168         LAYER_FUNC_ENTRY_VOID_RETURN();
1169         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1170
1171         _pthread_mutex_lock(&private_display->lock);
1172
1173         private_layer->buffer_queue = NULL;
1174
1175         _tdm_layer_free_all_buffers(private_layer);
1176
1177         _pthread_mutex_unlock(&private_display->lock);
1178 }
1179
1180 EXTERN tdm_error
1181 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1182 {
1183         tdm_func_layer *func_layer;
1184         LAYER_FUNC_ENTRY();
1185
1186         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1187
1188         _pthread_mutex_lock(&private_display->lock);
1189
1190         func_layer = &private_display->func_layer;
1191
1192         if (private_layer->usable)
1193                 TDM_INFO("layer(%p) not usable", private_layer);
1194
1195         private_layer->usable = 0;
1196
1197         if (!func_layer->layer_set_buffer) {
1198                 /* LCOV_EXCL_START */
1199                 _pthread_mutex_unlock(&private_display->lock);
1200                 TDM_ERR("not implemented!!");
1201                 return TDM_ERROR_NOT_IMPLEMENTED;
1202                 /* LCOV_EXCL_STOP */
1203         }
1204
1205         if (buffer_queue == private_layer->buffer_queue) {
1206                 _pthread_mutex_unlock(&private_display->lock);
1207                 return TDM_ERROR_NONE;
1208         }
1209
1210         if (private_layer->waiting_buffer) {
1211                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1212                 private_layer->waiting_buffer = NULL;
1213
1214                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1215                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1216                                          private_layer, private_layer->waiting_buffer);
1217         }
1218
1219         private_layer->buffer_queue = buffer_queue;
1220         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1221                                                                                 _tbm_layer_queue_acquirable_cb,
1222                                                                                 private_layer);
1223         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1224                                                                          _tbm_layer_queue_destroy_cb,
1225                                                                          private_layer);
1226         _pthread_mutex_unlock(&private_display->lock);
1227
1228         return ret;
1229 }
1230
1231 EXTERN tdm_error
1232 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1233 {
1234         return tdm_layer_unset_buffer(layer);
1235 }
1236
1237 EXTERN tdm_error
1238 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1239 {
1240         LAYER_FUNC_ENTRY();
1241
1242         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1243
1244         _pthread_mutex_lock(&private_display->lock);
1245
1246         *usable = private_layer->usable;
1247
1248         _pthread_mutex_unlock(&private_display->lock);
1249
1250         return ret;
1251 }
1252
1253 EXTERN tdm_error
1254 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1255 {
1256         tdm_func_layer *func_layer;
1257         LAYER_FUNC_ENTRY();
1258
1259         _pthread_mutex_lock(&private_display->lock);
1260
1261         func_layer = &private_display->func_layer;
1262
1263         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1264                 TDM_ERR("layer(%p) is not video layer", private_layer);
1265                 _pthread_mutex_unlock(&private_display->lock);
1266                 return TDM_ERROR_INVALID_PARAMETER;
1267         }
1268
1269         if (!func_layer->layer_set_video_pos) {
1270                 /* LCOV_EXCL_START */
1271                 _pthread_mutex_unlock(&private_display->lock);
1272                 TDM_ERR("not implemented!!");
1273                 return TDM_ERROR_NOT_IMPLEMENTED;
1274                 /* LCOV_EXCL_STOP */
1275         }
1276
1277         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1278
1279         _pthread_mutex_unlock(&private_display->lock);
1280
1281         return ret;
1282 }
1283
1284 EXTERN tdm_capture *
1285 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1286 {
1287         tdm_capture *capture = NULL;
1288
1289         LAYER_FUNC_ENTRY_ERROR();
1290
1291         _pthread_mutex_lock(&private_display->lock);
1292
1293         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1294
1295         _pthread_mutex_unlock(&private_display->lock);
1296
1297         return capture;
1298 }
1299
1300 EXTERN tdm_error
1301 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1302 {
1303         tdm_func_layer *func_layer;
1304         LAYER_FUNC_ENTRY();
1305         TDM_RETURN_VAL_IF_FAIL(flags != NULL, TDM_ERROR_INVALID_PARAMETER);
1306
1307         _pthread_mutex_lock(&private_display->lock);
1308
1309         func_layer = &private_display->func_layer;
1310
1311         if (!func_layer->layer_get_buffer_flags) {
1312                 /* LCOV_EXCL_START */
1313                 _pthread_mutex_unlock(&private_display->lock);
1314                 TDM_ERR("not implemented!!");
1315                 return TDM_ERROR_NOT_IMPLEMENTED;
1316                 /* LCOV_EXCL_STOP */
1317         }
1318
1319         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1320
1321         _pthread_mutex_unlock(&private_display->lock);
1322
1323         return ret;
1324 }