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