hwc:window_commit
[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 EXTERN tdm_error
209 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
210 {
211         tdm_func_layer *func_layer;
212         char fmtstr[128];
213
214         LAYER_FUNC_ENTRY();
215
216         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
217
218         _pthread_mutex_lock(&private_display->lock);
219
220         func_layer = &private_display->func_layer;
221
222         if (private_layer->usable)
223                 TDM_INFO("layer(%p) not usable", private_layer);
224
225         private_layer->usable = 0;
226
227         if (!func_layer->layer_set_info) {
228                 /* LCOV_EXCL_START */
229                 _pthread_mutex_unlock(&private_display->lock);
230                 TDM_ERR("not implemented!!");
231                 return TDM_ERROR_NOT_IMPLEMENTED;
232                 /* LCOV_EXCL_STOP */
233         }
234
235         if (info->src_config.format)
236                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
237         else
238                 snprintf(fmtstr, 128, "NONE");
239
240         TDM_INFO("layer(%p) info: src(%ux%u %u,%u %ux%u %s) dst(%u,%u %ux%u) trans(%d)",
241                          private_layer, info->src_config.size.h, info->src_config.size.v,
242                          info->src_config.pos.x, info->src_config.pos.y,
243                          info->src_config.pos.w, info->src_config.pos.h,
244                          fmtstr,
245                          info->dst_pos.x, info->dst_pos.y,
246                          info->dst_pos.w, info->dst_pos.h,
247                          info->transform);
248
249         private_layer->pending_info_changed = 1;
250         private_layer->pending_info = *info;
251
252         _pthread_mutex_unlock(&private_display->lock);
253
254         return ret;
255 }
256
257 EXTERN tdm_error
258 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
259 {
260         tdm_func_layer *func_layer;
261         LAYER_FUNC_ENTRY();
262
263         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
264
265         _pthread_mutex_lock(&private_display->lock);
266
267         func_layer = &private_display->func_layer;
268
269         if (!func_layer->layer_get_info) {
270                 /* LCOV_EXCL_START */
271                 _pthread_mutex_unlock(&private_display->lock);
272                 TDM_ERR("not implemented!!");
273                 return TDM_ERROR_NOT_IMPLEMENTED;
274                 /* LCOV_EXCL_STOP */
275         }
276
277         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
278
279         _pthread_mutex_unlock(&private_display->lock);
280
281         return ret;
282 }
283
284 /* LCOV_EXCL_START */
285 static void
286 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
287 {
288         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
289         tdm_private_output *private_output = private_layer->private_output;
290         unsigned int pipe;
291         char fname[TDM_PATH_LEN], bufs[TDM_PATH_LEN];
292         int zpos, len = TDM_PATH_LEN;
293         tdm_private_layer *l = NULL;
294         char *p = bufs;
295         int *remain = &len;
296
297         pipe = private_output->pipe;
298         zpos = private_layer->caps.zpos;
299
300         bufs[0] = '\0';
301         LIST_FOR_EACH_ENTRY(l, &private_output->layer_list, link) {
302                 if (!l->showing_buffer)
303                         continue;
304                 TDM_SNPRINTF(p, remain, "_%p", l->showing_buffer->buffer);
305         }
306
307         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d%s", pipe, zpos, bufs);
308
309         tbm_surface_internal_dump_buffer(buffer, fname);
310         TDM_DBG("%s dump excute", fname);
311
312         return;
313 }
314 /* LCOV_EXCL_STOP */
315
316 static void
317 _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer)
318 {
319         tdm_private_display *private_display;
320
321         if (!layer_buffer)
322                 return;
323
324         private_display = private_layer->private_output->private_display;
325
326         LIST_DEL(&layer_buffer->link);
327         if (layer_buffer->buffer) {
328                 _pthread_mutex_unlock(&private_display->lock);
329                 tdm_buffer_unref_backend(layer_buffer->buffer);
330                 if (private_layer->buffer_queue)
331                         tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer);
332                 _pthread_mutex_lock(&private_display->lock);
333         }
334         free(layer_buffer);
335 }
336
337 static void
338 _tdm_layer_free_all_buffers(tdm_private_layer *private_layer)
339 {
340         tdm_private_output *private_output = private_layer->private_output;
341         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
342         struct list_head clone_list;
343
344         LIST_INITHEAD(&clone_list);
345
346         _tdm_layer_reset_pending_data(private_layer);
347
348         if (private_layer->waiting_buffer) {
349                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
350                 private_layer->waiting_buffer = NULL;
351
352                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
353                         TDM_INFO("layer(%p) waiting_buffer(%p)",
354                                          private_layer, private_layer->waiting_buffer);
355         }
356
357         if (private_layer->committed_buffer) {
358                 _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
359                 private_layer->committed_buffer = NULL;
360
361                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
362                         TDM_INFO("layer(%p) committed_buffer(%p)",
363                                          private_layer, private_layer->committed_buffer);
364         }
365
366         if (private_layer->showing_buffer) {
367                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
368                 private_layer->showing_buffer = NULL;
369
370                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
371                         TDM_INFO("layer(%p) showing_buffer(%p)",
372                                          private_layer, private_layer->showing_buffer);
373         }
374
375         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
376                 if (lm->private_layer != private_layer)
377                         continue;
378                 LIST_DEL(&lm->link);
379                 LIST_ADDTAIL(&lm->link, &clone_list);
380         }
381
382         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
383                 LIST_DEL(&lm->link);
384                 tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
385                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
386                 free(lm);
387         }
388
389         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
390                 if (lm->private_layer != private_layer)
391                         continue;
392                 LIST_DEL(&lm->link);
393                 LIST_ADDTAIL(&lm->link, &clone_list);
394         }
395
396         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
397                 LIST_DEL(&lm->link);
398                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
399                 free(lm);
400         }
401
402         if (private_layer->buffer_queue) {
403                 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer);
404                 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer);
405                 private_layer->buffer_queue = NULL;
406         }
407 }
408
409 INTERN tdm_error
410 tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h buffer)
411 {
412         tdm_func_layer *func_layer;
413
414         /* LCOV_EXCL_START */
415         /* dump buffer */
416         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
417                 _tdm_layer_dump_buffer(private_layer, buffer);
418
419         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
420                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
421                 char str[TDM_PATH_LEN];
422                 static int i;
423                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
424                                  private_output->index, private_layer->index, i++);
425                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
426         }
427         /* LCOV_EXCL_STOP */
428
429         func_layer = &private_display->func_layer;
430
431         if (private_layer->usable)
432                 TDM_INFO("layer(%p) not usable", private_layer);
433
434         private_layer->usable = 0;
435
436         if (!func_layer->layer_set_buffer) {
437                 /* LCOV_EXCL_START */
438                 TDM_ERR("not implemented!!");
439                 return TDM_ERROR_NOT_IMPLEMENTED;
440                 /* LCOV_EXCL_START */
441         }
442
443         private_layer->pending_buffer_changed = 1;
444
445         if (private_layer->pending_buffer) {
446
447                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
448                         TDM_INFO("layer(%p) pending_buffer(%p) skipped",
449                                          private_layer, private_layer->pending_buffer);
450
451                 if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
452                         tbm_bo bo = tbm_surface_internal_get_bo(private_layer->pending_buffer, 0);
453                         TDM_TRACE_ASYNC_END((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
454                 }
455
456                 tbm_surface_internal_unref(private_layer->pending_buffer);
457         }
458
459         tbm_surface_internal_ref(buffer);
460         private_layer->pending_buffer = buffer;
461
462         if (tdm_debug_module & TDM_DEBUG_BUFFER)
463                 TDM_INFO("layer(%p) pending_buffer(%p)",
464                                  private_layer, private_layer->pending_buffer);
465
466         if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
467                 tbm_bo bo = tbm_surface_internal_get_bo(private_layer->pending_buffer, 0);
468                 TDM_TRACE_ASYNC_BEGIN((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
469         }
470
471         return TDM_ERROR_NONE;
472 }
473
474 EXTERN tdm_error
475 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
476 {
477         LAYER_FUNC_ENTRY();
478
479         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
480
481         _pthread_mutex_lock(&private_display->lock);
482
483         ret = tdm_layer_set_buffer_internal(private_layer, buffer);
484
485         _pthread_mutex_unlock(&private_display->lock);
486
487         return ret;
488 }
489
490 INTERN tdm_error
491 tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer)
492 {
493         tdm_func_layer *func_layer;
494         LAYER_FUNC_ENTRY();
495
496         func_layer = &private_display->func_layer;
497
498         _tdm_layer_free_all_buffers(private_layer);
499
500         private_layer->usable = 1;
501
502         if (private_layer->usable)
503                 TDM_INFO("layer(%p) now usable", private_layer);
504
505         if (!func_layer->layer_unset_buffer) {
506                 /* LCOV_EXCL_START */
507                 TDM_ERR("not implemented!!");
508                 return TDM_ERROR_NOT_IMPLEMENTED;
509                 /* LCOV_EXCL_START */
510         }
511
512         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
513         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
514
515         return ret;
516 }
517
518 EXTERN tdm_error
519 tdm_layer_unset_buffer(tdm_layer *layer)
520 {
521         LAYER_FUNC_ENTRY();
522
523         _pthread_mutex_lock(&private_display->lock);
524
525         ret = tdm_layer_unset_buffer_internal(private_layer);
526
527         _pthread_mutex_unlock(&private_display->lock);
528
529         return ret;
530 }
531
532 INTERN void
533 tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
534 {
535         tdm_private_output *private_output = private_layer->private_output;
536         tdm_private_display *private_display = private_output->private_display;
537
538         /* LCOV_EXCL_START */
539         if (private_display->print_fps) {
540                 double curr = tdm_helper_get_time();
541                 if (private_layer->fps_stamp == 0) {
542                         private_layer->fps_stamp = curr;
543                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
544                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
545                         private_layer->fps_count = 0;
546                         private_layer->fps_stamp = curr;
547                 } else
548                         private_layer->fps_count++;
549         } else if (private_layer->fps_stamp != 0) {
550                 private_layer->fps_stamp = 0;
551                 private_layer->fps_count = 0;
552         }
553         /* LCOV_EXCL_STOP */
554
555         if (private_layer->showing_buffer) {
556                 if (tdm_ttrace_module & TDM_TTRACE_LAYER) {
557                         tbm_bo bo = tbm_surface_internal_get_bo(private_layer->showing_buffer->buffer, 0);
558                         TDM_TRACE_ASYNC_END((intptr_t)private_layer, "[LAYER] %d", tbm_bo_export(bo));
559                 }
560
561                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
562         }
563
564         private_layer->showing_buffer = *committed_buffer;
565         *committed_buffer = NULL;
566
567         if (tdm_debug_module & TDM_DEBUG_BUFFER)
568                 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
569                                  private_layer, *committed_buffer,
570                                  (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
571 }
572
573 static void
574 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
575                                                          unsigned int tv_sec, unsigned int tv_usec)
576 {
577         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
578         tdm_private_display *private_display;
579         struct list_head clone_list, pending_clone_list;
580         tdm_error ret = TDM_ERROR_NONE;
581
582         private_display = private_output->private_display;
583
584         private_output->layer_waiting_vblank = 0;
585
586         LIST_INITHEAD(&clone_list);
587         LIST_INITHEAD(&pending_clone_list);
588
589         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
590                 LIST_DEL(&lm->link);
591                 lm->private_layer->committing = 0;
592                 LIST_ADDTAIL(&lm->link, &clone_list);
593         }
594
595         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
596                 LIST_DEL(&lm->link);
597                 lm->private_layer->committing = 0;
598                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
599         }
600
601         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
602                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
603                         TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
604                                          lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
605
606                 LIST_DEL(&lm->link);
607                 tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
608                 _pthread_mutex_unlock(&private_display->lock);
609                 if (lm->func)
610                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
611                 _pthread_mutex_lock(&private_display->lock);
612                 if (lm->committed_buffer)
613                         _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
614                 free(lm);
615         }
616
617         if (LIST_IS_EMPTY(&pending_clone_list))
618                 return;
619
620         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
621
622         ret = tdm_output_commit_internal(private_output, 0, NULL, NULL);
623         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
624
625         if (tdm_debug_module & TDM_DEBUG_COMMIT)
626                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
627
628         if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
629                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
630                 if (!private_output->layer_waiting_vblank) {
631                         _pthread_mutex_unlock(&private_display->lock);
632                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
633                         _pthread_mutex_lock(&private_display->lock);
634                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
635                         private_output->layer_waiting_vblank = 1;
636                 }
637         }
638
639         if (tdm_debug_module & TDM_DEBUG_COMMIT)
640                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
641
642         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
643                 LIST_DEL(&lm->link);
644                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
645         }
646
647         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
648                 TDM_WRN("dpms %s. Directly call vblank callback.", tdm_dpms_str(private_output->current_dpms_value));
649                 _pthread_mutex_unlock(&private_display->lock);
650                 _tdm_layer_cb_wait_vblank(private_output->vblank, 0, 0, 0, 0, private_output);
651                 _pthread_mutex_lock(&private_display->lock);
652         }
653
654         return;
655 wait_failed:
656         /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
657          * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
658          * the layer commit handler MUST be called.
659          */
660         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
661                 TDM_WRN("Directly call layer commit handlers: ret(%d)\n", ret);
662                 LIST_DEL(&lm->link);
663                 _pthread_mutex_unlock(&private_display->lock);
664                 if (lm->func)
665                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
666                 _pthread_mutex_lock(&private_display->lock);
667                 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
668                 free(lm);
669         }
670
671         return;
672 }
673
674 static void
675 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
676                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
677 {
678         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
679         tdm_private_layer_commit_handler *lm = NULL;
680         tdm_private_display *private_display;
681         tdm_private_output *private_output = output;
682         tdm_private_layer *private_layer;
683         int found = 0;
684
685         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
686
687         private_display = private_output->private_display;
688
689         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
690                 if (layer_commit_handler == lm) {
691                         found = 1;
692                         break;
693                 }
694         }
695
696         if (!found)
697                 return;
698
699         LIST_DEL(&layer_commit_handler->link);
700
701         private_layer = layer_commit_handler->private_layer;
702
703         if (tdm_debug_module & TDM_DEBUG_COMMIT)
704                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
705                                  private_layer, private_output->pipe, layer_commit_handler);
706
707         _pthread_mutex_lock(&private_display->lock);
708
709         tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
710
711         if (layer_commit_handler->func) {
712                 _pthread_mutex_unlock(&private_display->lock);
713                 layer_commit_handler->func(private_output, sequence,
714                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
715                 _pthread_mutex_lock(&private_display->lock);
716         }
717
718         free(layer_commit_handler);
719
720         _pthread_mutex_unlock(&private_display->lock);
721 }
722
723 static void
724 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
725                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
726 {
727         tdm_private_output *private_output = user_data;
728         tdm_private_display *private_display;
729
730         TDM_RETURN_IF_FAIL(private_output != NULL);
731
732         private_display = private_output->private_display;
733
734         _pthread_mutex_lock(&private_display->lock);
735
736         if (tdm_debug_module & TDM_DEBUG_COMMIT)
737                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
738
739         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
740
741         _pthread_mutex_unlock(&private_display->lock);
742 }
743
744 static unsigned int
745 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
746 {
747         tdm_private_layer *private_layer = NULL;
748         unsigned int count = 0;
749
750         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
751                 if (!private_layer->usable)
752                         count++;
753         }
754
755         return count;
756 }
757
758 /* commit_per_vblank == 1: we can commit if
759  *                           - there is no previous commit request
760  *                           - only 1 layer is used
761  * commit_per_vblank == 2: we can commit if
762  *                           - there is no previous commit request
763  */
764 static int
765 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
766 {
767         tdm_private_output *private_output = private_layer->private_output;
768
769         TDM_RETURN_VAL_IF_FAIL(private_output->commit_per_vblank > 0, 1);
770
771         /* There is a previous commit request which is not done and displayed on screen yet.
772          * We can't commit at this time.
773          */
774         if (!LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
775                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
776                         TDM_INFO("layer(%p) commit: not possible(previous commit)", private_layer);
777                 return 0;
778         }
779
780         if (private_output->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) {
781                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
782                         TDM_INFO("layer(%p) commit: not possible(more than 2 layers)", private_layer);
783                 return 0;
784         }
785
786         if (tdm_debug_module & TDM_DEBUG_COMMIT)
787                 TDM_INFO("layer(%p) commit: possible", private_layer);
788
789         return 1;
790 }
791
792 static void
793 _tdm_layer_reset_pending_data(tdm_private_layer *private_layer)
794 {
795         private_layer->pending_info_changed = 0;
796         memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info);
797
798         private_layer->pending_buffer_changed = 0;
799         if (private_layer->pending_buffer) {
800                 tbm_surface_internal_unref(private_layer->pending_buffer);
801                 private_layer->pending_buffer = NULL;
802         }
803 }
804
805 INTERN tdm_error
806 tdm_layer_commit_pending_data(tdm_private_layer *private_layer)
807 {
808         tdm_private_output *private_output = private_layer->private_output;
809         tdm_private_display *private_display = private_output->private_display;
810         tdm_func_layer *func_layer;
811         tdm_error ret = TDM_ERROR_NONE;
812
813         func_layer = &private_display->func_layer;
814
815         if (private_layer->pending_info_changed) {
816                 ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info);
817                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
818         }
819
820         if (private_layer->pending_buffer_changed) {
821                 tdm_private_layer_buffer *layer_buffer;
822
823                 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
824                 TDM_GOTO_IF_FAIL(layer_buffer != NULL, done);
825
826                 LIST_INITHEAD(&layer_buffer->link);
827
828                 ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer);
829                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
830
831                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
832                         TDM_INFO("layer(%p) pending_buffer(%p) committed",
833                                          private_layer, private_layer->pending_buffer);
834
835                 if (ret == TDM_ERROR_NONE) {
836                         if (private_layer->waiting_buffer)
837                                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
838
839                         private_layer->waiting_buffer = layer_buffer;
840                         private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer);
841                         if (tdm_debug_module & TDM_DEBUG_BUFFER)
842                                 TDM_INFO("layer(%p) waiting_buffer(%p)",
843                                                  private_layer, private_layer->waiting_buffer->buffer);
844                 } else
845                         _tdm_layer_free_buffer(private_layer, layer_buffer);
846         }
847
848 done:
849         _tdm_layer_reset_pending_data(private_layer);
850
851         return ret;
852 }
853
854 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
855  * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
856  * the layer commit handler MUST be called.
857  */
858 static tdm_error
859 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
860 {
861         tdm_private_layer_commit_handler *layer_commit_handler;
862         LAYER_FUNC_ENTRY();
863
864         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
865         if (!layer_commit_handler) {
866                 /* LCOV_EXCL_START */
867                 TDM_ERR("failed: alloc memory");
868                 return TDM_ERROR_OUT_OF_MEMORY;
869                 /* LCOV_EXCL_STOP */
870         }
871
872         if (tdm_debug_module & TDM_DEBUG_COMMIT)
873                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
874
875         LIST_INITHEAD(&layer_commit_handler->link);
876         layer_commit_handler->private_layer = private_layer;
877         layer_commit_handler->func = func;
878         layer_commit_handler->user_data = user_data;
879
880         layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
881         private_layer->waiting_buffer = NULL;
882
883         if (tdm_debug_module & TDM_DEBUG_BUFFER)
884                 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
885                                  private_layer, private_layer->waiting_buffer,
886                                  (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
887
888         if (!private_output->commit_per_vblank) {
889                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
890
891                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
892                 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
893                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
894
895                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
896                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
897         } else {
898                 TDM_GOTO_IF_FAIL(private_output->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
899
900                 if (private_layer->committing)
901                         TDM_WRN("layer(%d) too many commit", private_layer->index);
902                 else
903                         private_layer->committing = 1;
904
905                 if (_tdm_layer_commit_possible(private_layer)) {
906                         /* add to layer_commit_handler_list */
907                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
908                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
909                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
910
911                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
912                                 TDM_INFO("layer(%p) commit: output", private_layer);
913                 } else {
914                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
915                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
916
917                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
918                                 TDM_INFO("layer(%p) commit: pending", private_layer);
919                 }
920
921                 if (!private_output->vblank) {
922                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
923                         _pthread_mutex_unlock(&private_display->lock);
924                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
925                         _pthread_mutex_lock(&private_display->lock);
926                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
927                 }
928
929                 if (!private_output->layer_waiting_vblank) {
930                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
931                         _pthread_mutex_unlock(&private_display->lock);
932                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
933                         _pthread_mutex_lock(&private_display->lock);
934                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
935                         private_output->layer_waiting_vblank = 1;
936
937                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
938                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
939                 }
940         }
941
942         return ret;
943
944 commit_failed:
945         if (layer_commit_handler) {
946                 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
947                 LIST_DEL(&layer_commit_handler->link);
948                 free(layer_commit_handler);
949         }
950         return ret;
951 }
952
953 INTERN tdm_error
954 tdm_layer_commit_internal(tdm_private_layer *private_layer, tdm_layer_commit_handler func, void *user_data)
955 {
956         tdm_private_output *private_output = private_layer->private_output;
957         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */
958
959         if (private_output->commit_type == TDM_COMMIT_TYPE_NONE) {
960                 if (!private_output->commit_per_vblank)
961                         private_output->commit_type = TDM_COMMIT_TYPE_OUTPUT;
962                 else
963                         private_output->commit_type = TDM_COMMIT_TYPE_LAYER;
964         }
965
966         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
967                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", private_layer, private_output->pipe,
968                                 tdm_dpms_str(private_output->current_dpms_value));
969                 return TDM_ERROR_DPMS_OFF;
970         }
971
972         /* don't call this inside of _tdm_layer_commit */
973         ret = tdm_layer_commit_pending_data(private_layer);
974         if (ret != TDM_ERROR_NONE) {
975                 TDM_ERR("layer(%p) committing pending data failed", private_layer);
976                 return ret;
977         }
978
979         ret = _tdm_layer_commit(private_layer, func, user_data);
980
981         return ret;
982 }
983
984 EXTERN tdm_error
985 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
986 {
987         LAYER_FUNC_ENTRY();
988
989         _pthread_mutex_lock(&private_display->lock);
990
991         ret = tdm_layer_commit_internal(private_layer, func, user_data);
992
993         _pthread_mutex_unlock(&private_display->lock);
994
995         return ret;
996 }
997
998 EXTERN tdm_error
999 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
1000 {
1001         LAYER_FUNC_ENTRY();
1002
1003         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
1004
1005         _pthread_mutex_lock(&private_display->lock);
1006
1007         *committing = private_layer->committing;
1008
1009         _pthread_mutex_unlock(&private_display->lock);
1010
1011         return ret;
1012 }
1013
1014 INTERN void
1015 tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1016 {
1017         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
1018         tdm_private_output *private_output = private_layer->private_output;
1019         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
1020
1021         TDM_RETURN_IF_FAIL(private_layer != NULL);
1022         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
1023
1024         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
1025                 if (lm->func == func && lm->user_data == user_data) {
1026                         LIST_DEL(&lm->link);
1027                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1028                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1029                         free(lm);
1030                         break;
1031                 }
1032         }
1033
1034         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
1035                 if (lm->func == func && lm->user_data == user_data) {
1036                         LIST_DEL(&lm->link);
1037                         tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
1038                         _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1039                         free(lm);
1040                         break;
1041                 }
1042         }
1043 }
1044
1045 EXTERN tdm_error
1046 tdm_layer_remove_commit_handler(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1047 {
1048         LAYER_FUNC_ENTRY();
1049
1050         _pthread_mutex_lock(&private_display->lock);
1051
1052         tdm_layer_remove_commit_handler_internal(layer, func, user_data);
1053
1054         _pthread_mutex_unlock(&private_display->lock);
1055
1056         return ret;
1057 }
1058
1059 EXTERN tbm_surface_h
1060 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1061 {
1062         tbm_surface_h buffer;
1063         LAYER_FUNC_ENTRY_ERROR();
1064
1065         _pthread_mutex_lock(&private_display->lock);
1066
1067         if (error)
1068                 *error = TDM_ERROR_NONE;
1069
1070         if (private_layer->showing_buffer) {
1071                 buffer = private_layer->showing_buffer->buffer;
1072         } else {
1073                 if (error)
1074                         *error = TDM_ERROR_OPERATION_FAILED;
1075                 _pthread_mutex_unlock(&private_display->lock);
1076                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1077                 return NULL;
1078         }
1079         _pthread_mutex_unlock(&private_display->lock);
1080
1081         return buffer;
1082 }
1083
1084 static void
1085 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1086 {
1087         TDM_RETURN_IF_FAIL(data != NULL);
1088         tdm_layer *layer = data;
1089         tdm_func_layer *func_layer;
1090         tbm_surface_h surface = NULL;
1091         tdm_private_layer_buffer *layer_buffer;
1092         LAYER_FUNC_ENTRY_VOID_RETURN();
1093
1094         _pthread_mutex_lock(&private_display->lock);
1095
1096         func_layer = &private_display->func_layer;
1097         if (!func_layer->layer_set_buffer) {
1098                 /* LCOV_EXCL_START */
1099                 _pthread_mutex_unlock(&private_display->lock);
1100                 return;
1101                 /* LCOV_EXCL_STOP */
1102         }
1103
1104         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
1105         if (!layer_buffer) {
1106                 /* LCOV_EXCL_START */
1107                 _pthread_mutex_unlock(&private_display->lock);
1108                 TDM_ERR("alloc failed");
1109                 return;
1110                 /* LCOV_EXCL_STOP */
1111         }
1112         LIST_INITHEAD(&layer_buffer->link);
1113
1114         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1115                 surface == NULL) {
1116                 /* LCOV_EXCL_START */
1117                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1118                                 private_layer, surface);
1119                 _pthread_mutex_unlock(&private_display->lock);
1120                 free(layer_buffer);
1121                 return;
1122                 /* LCOV_EXCL_STOP */
1123         }
1124
1125         /* we don't need to handle pending data here because the changes in this function
1126          * should be applied immediately. we can't expect calling tdm_layer_commit.
1127          */
1128         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1129         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1130
1131         if (ret == TDM_ERROR_NONE) {
1132                 if (private_layer->waiting_buffer) {
1133                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
1134                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1135                 }
1136
1137                 private_layer->waiting_buffer = layer_buffer;
1138                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
1139
1140                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1141                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1142                                          private_layer, private_layer->waiting_buffer->buffer);
1143
1144                 if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1145                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
1146                         if (ret != TDM_ERROR_NONE)
1147                                 TDM_ERR("tdm_output_commit_internal() is fail");
1148                 } else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) {
1149                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
1150                         if (ret != TDM_ERROR_NONE)
1151                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
1152                 } else {
1153                         TDM_NEVER_GET_HERE();
1154                 }
1155         } else
1156                 _tdm_layer_free_buffer(private_layer, layer_buffer);
1157
1158         _pthread_mutex_unlock(&private_display->lock);
1159 }
1160
1161 static void
1162 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1163 {
1164         TDM_RETURN_IF_FAIL(data != NULL);
1165         tdm_layer *layer = data;
1166         LAYER_FUNC_ENTRY_VOID_RETURN();
1167         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1168
1169         _pthread_mutex_lock(&private_display->lock);
1170
1171         private_layer->buffer_queue = NULL;
1172
1173         _tdm_layer_free_all_buffers(private_layer);
1174
1175         _pthread_mutex_unlock(&private_display->lock);
1176 }
1177
1178 EXTERN tdm_error
1179 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1180 {
1181         tdm_func_layer *func_layer;
1182         LAYER_FUNC_ENTRY();
1183
1184         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1185
1186         _pthread_mutex_lock(&private_display->lock);
1187
1188         func_layer = &private_display->func_layer;
1189
1190         if (private_layer->usable)
1191                 TDM_INFO("layer(%p) not usable", private_layer);
1192
1193         private_layer->usable = 0;
1194
1195         if (!func_layer->layer_set_buffer) {
1196                 /* LCOV_EXCL_START */
1197                 _pthread_mutex_unlock(&private_display->lock);
1198                 TDM_ERR("not implemented!!");
1199                 return TDM_ERROR_NOT_IMPLEMENTED;
1200                 /* LCOV_EXCL_STOP */
1201         }
1202
1203         if (buffer_queue == private_layer->buffer_queue) {
1204                 _pthread_mutex_unlock(&private_display->lock);
1205                 return TDM_ERROR_NONE;
1206         }
1207
1208         if (private_layer->waiting_buffer) {
1209                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1210                 private_layer->waiting_buffer = NULL;
1211
1212                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1213                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1214                                          private_layer, private_layer->waiting_buffer);
1215         }
1216
1217         private_layer->buffer_queue = buffer_queue;
1218         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1219                                                                                 _tbm_layer_queue_acquirable_cb,
1220                                                                                 private_layer);
1221         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1222                                                                          _tbm_layer_queue_destroy_cb,
1223                                                                          private_layer);
1224         _pthread_mutex_unlock(&private_display->lock);
1225
1226         return ret;
1227 }
1228
1229 EXTERN tdm_error
1230 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1231 {
1232         return tdm_layer_unset_buffer(layer);
1233 }
1234
1235 EXTERN tdm_error
1236 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1237 {
1238         LAYER_FUNC_ENTRY();
1239
1240         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1241
1242         _pthread_mutex_lock(&private_display->lock);
1243
1244         *usable = private_layer->usable;
1245
1246         _pthread_mutex_unlock(&private_display->lock);
1247
1248         return ret;
1249 }
1250
1251 EXTERN tdm_error
1252 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1253 {
1254         tdm_func_layer *func_layer;
1255         LAYER_FUNC_ENTRY();
1256
1257         _pthread_mutex_lock(&private_display->lock);
1258
1259         func_layer = &private_display->func_layer;
1260
1261         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1262                 TDM_ERR("layer(%p) is not video layer", private_layer);
1263                 _pthread_mutex_unlock(&private_display->lock);
1264                 return TDM_ERROR_INVALID_PARAMETER;
1265         }
1266
1267         if (!func_layer->layer_set_video_pos) {
1268                 /* LCOV_EXCL_START */
1269                 _pthread_mutex_unlock(&private_display->lock);
1270                 TDM_ERR("not implemented!!");
1271                 return TDM_ERROR_NOT_IMPLEMENTED;
1272                 /* LCOV_EXCL_STOP */
1273         }
1274
1275         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1276
1277         _pthread_mutex_unlock(&private_display->lock);
1278
1279         return ret;
1280 }
1281
1282 EXTERN tdm_capture *
1283 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1284 {
1285         tdm_capture *capture = NULL;
1286
1287         LAYER_FUNC_ENTRY_ERROR();
1288
1289         _pthread_mutex_lock(&private_display->lock);
1290
1291         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1292
1293         _pthread_mutex_unlock(&private_display->lock);
1294
1295         return capture;
1296 }
1297
1298 EXTERN tdm_error
1299 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1300 {
1301         tdm_func_layer *func_layer;
1302         LAYER_FUNC_ENTRY();
1303         TDM_RETURN_VAL_IF_FAIL(flags != NULL, TDM_ERROR_INVALID_PARAMETER);
1304
1305         _pthread_mutex_lock(&private_display->lock);
1306
1307         func_layer = &private_display->func_layer;
1308
1309         if (!func_layer->layer_get_buffer_flags) {
1310                 /* LCOV_EXCL_START */
1311                 _pthread_mutex_unlock(&private_display->lock);
1312                 TDM_ERR("not implemented!!");
1313                 return TDM_ERROR_NOT_IMPLEMENTED;
1314                 /* LCOV_EXCL_STOP */
1315         }
1316
1317         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1318
1319         _pthread_mutex_unlock(&private_display->lock);
1320
1321         return ret;
1322 }