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