layer: call the layer commit handlers once tdm_layer_commit returns success
[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.h"
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
44
45 #define COUNT_MAX   10
46
47 #define LAYER_FUNC_ENTRY() \
48         tdm_private_display *private_display; \
49         tdm_private_output *private_output; \
50         tdm_private_layer *private_layer; \
51         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
52         TDM_RETURN_VAL_IF_FAIL(layer != NULL, TDM_ERROR_INVALID_PARAMETER); \
53         private_layer = (tdm_private_layer*)layer; \
54         private_output = private_layer->private_output; \
55         private_display = private_output->private_display
56
57 #define LAYER_FUNC_ENTRY_ERROR() \
58         tdm_private_display *private_display; \
59         tdm_private_output *private_output; \
60         tdm_private_layer *private_layer; \
61         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
62         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(layer != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
63         private_layer = (tdm_private_layer*)layer; \
64         private_output = private_layer->private_output; \
65         private_display = private_output->private_display
66
67 #define LAYER_FUNC_ENTRY_VOID_RETURN() \
68         tdm_private_display *private_display; \
69         tdm_private_output *private_output; \
70         tdm_private_layer *private_layer; \
71         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
72         TDM_RETURN_IF_FAIL(layer != NULL); \
73         private_layer = (tdm_private_layer*)layer; \
74         private_output = private_layer->private_output; \
75         private_display = private_output->private_display
76
77 static void _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer);
78 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
79                                                                           unsigned int tv_sec, unsigned int tv_usec, void *user_data);
80 static void _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data);
81 static void _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data);
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                 _pthread_mutex_unlock(&private_display->lock);
168                 TDM_ERR("not implemented!!");
169                 return TDM_ERROR_NOT_IMPLEMENTED;
170         }
171
172         ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
173
174         _pthread_mutex_unlock(&private_display->lock);
175
176         return ret;
177 }
178
179 EXTERN tdm_error
180 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
181 {
182         tdm_func_layer *func_layer;
183         LAYER_FUNC_ENTRY();
184
185         TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
186
187         _pthread_mutex_lock(&private_display->lock);
188
189         func_layer = &private_display->func_layer;
190
191         if (!func_layer->layer_get_property) {
192                 _pthread_mutex_unlock(&private_display->lock);
193                 TDM_ERR("not implemented!!");
194                 return TDM_ERROR_NOT_IMPLEMENTED;
195         }
196
197         ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
198
199         _pthread_mutex_unlock(&private_display->lock);
200
201         return ret;
202 }
203
204 EXTERN tdm_error
205 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
206 {
207         tdm_func_layer *func_layer;
208         char fmtstr[128];
209
210         LAYER_FUNC_ENTRY();
211
212         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
213
214         _pthread_mutex_lock(&private_display->lock);
215
216         func_layer = &private_display->func_layer;
217
218         if (private_layer->usable)
219                 TDM_INFO("layer(%p) not usable", private_layer);
220
221         private_layer->usable = 0;
222
223         if (!func_layer->layer_set_info) {
224                 _pthread_mutex_unlock(&private_display->lock);
225                 TDM_ERR("not implemented!!");
226                 return TDM_ERROR_NOT_IMPLEMENTED;
227         }
228
229         if (info->src_config.format)
230                 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
231         else
232                 snprintf(fmtstr, 128, "NONE");
233
234         TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
235                          private_layer, info->src_config.size.h, info->src_config.size.v,
236                          info->src_config.pos.x, info->src_config.pos.y,
237                          info->src_config.pos.w, info->src_config.pos.h,
238                          fmtstr,
239                          info->dst_pos.x, info->dst_pos.y,
240                          info->dst_pos.w, info->dst_pos.h,
241                          info->transform);
242
243         ret = func_layer->layer_set_info(private_layer->layer_backend, info);
244         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
245
246         _pthread_mutex_unlock(&private_display->lock);
247
248         return ret;
249 }
250
251 EXTERN tdm_error
252 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
253 {
254         tdm_func_layer *func_layer;
255         LAYER_FUNC_ENTRY();
256
257         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
258
259         _pthread_mutex_lock(&private_display->lock);
260
261         func_layer = &private_display->func_layer;
262
263         if (!func_layer->layer_get_info) {
264                 _pthread_mutex_unlock(&private_display->lock);
265                 TDM_ERR("not implemented!!");
266                 return TDM_ERROR_NOT_IMPLEMENTED;
267         }
268
269         ret = func_layer->layer_get_info(private_layer->layer_backend, info);
270
271         _pthread_mutex_unlock(&private_display->lock);
272
273         return ret;
274 }
275
276 static void
277 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
278 {
279         tdm_private_layer *private_layer = (tdm_private_layer*)layer;
280         tdm_private_output *private_output = private_layer->private_output;
281         unsigned int pipe;
282         int zpos;
283         char fname[PATH_MAX];
284
285         pipe = private_output->pipe;
286         zpos = private_layer->caps.zpos;
287
288         snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos);
289
290         tbm_surface_internal_dump_buffer(buffer, fname);
291         TDM_DBG("%s dump excute", fname);
292
293         return;
294 }
295
296 static void
297 _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer)
298 {
299         tdm_private_display *private_display;
300
301         if (!layer_buffer)
302                 return;
303
304         private_display = private_layer->private_output->private_display;
305
306         LIST_DEL(&layer_buffer->link);
307         if (layer_buffer->buffer) {
308                 _pthread_mutex_unlock(&private_display->lock);
309                 tdm_buffer_unref_backend(layer_buffer->buffer);
310                 if (private_layer->buffer_queue)
311                         tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer);
312                 _pthread_mutex_lock(&private_display->lock);
313         }
314         free(layer_buffer);
315 }
316
317 static void
318 _tdm_layer_free_all_buffers(tdm_private_layer *private_layer)
319 {
320         tdm_private_output *private_output = private_layer->private_output;
321         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
322         struct list_head clone_list;
323
324         LIST_INITHEAD(&clone_list);
325
326         if (private_layer->waiting_buffer) {
327                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
328                 private_layer->waiting_buffer = NULL;
329
330                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
331                         TDM_INFO("layer(%p) waiting_buffer(%p)",
332                                          private_layer, private_layer->waiting_buffer);
333         }
334
335         if (private_layer->committed_buffer) {
336                 _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
337                 private_layer->committed_buffer = NULL;
338
339                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
340                         TDM_INFO("layer(%p) committed_buffer(%p)",
341                                          private_layer, private_layer->committed_buffer);
342         }
343
344         if (private_layer->showing_buffer) {
345                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
346                 private_layer->showing_buffer = NULL;
347
348                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
349                         TDM_INFO("layer(%p) showing_buffer(%p)",
350                                          private_layer, private_layer->showing_buffer);
351         }
352
353         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
354                 if (lm->private_layer != private_layer)
355                         continue;
356                 LIST_DEL(&lm->link);
357                 LIST_ADDTAIL(&lm->link, &clone_list);
358         }
359
360         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
361                 LIST_DEL(&lm->link);
362                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
363                 free(lm);
364         }
365
366         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
367                 if (lm->private_layer != private_layer)
368                         continue;
369                 LIST_DEL(&lm->link);
370                 LIST_ADDTAIL(&lm->link, &clone_list);
371         }
372
373         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
374                 LIST_DEL(&lm->link);
375                 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
376                 free(lm);
377         }
378
379         if (private_layer->buffer_queue) {
380                 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer);
381                 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer);
382                 private_layer->buffer_queue = NULL;
383         }
384 }
385
386 EXTERN tdm_error
387 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
388 {
389         tdm_func_layer *func_layer;
390         tdm_private_layer_buffer *layer_buffer;
391
392         LAYER_FUNC_ENTRY();
393
394         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
395
396         _pthread_mutex_lock(&private_display->lock);
397
398         if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
399                 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
400                 char str[TDM_PATH_LEN];
401                 static int i;
402                 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
403                                  private_output->index, private_layer->index, i++);
404                 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
405         }
406
407         func_layer = &private_display->func_layer;
408
409         if (private_layer->usable)
410                 TDM_INFO("layer(%p) not usable", private_layer);
411
412         private_layer->usable = 0;
413
414         if (!func_layer->layer_set_buffer) {
415                 _pthread_mutex_unlock(&private_display->lock);
416                 TDM_ERR("not implemented!!");
417                 return TDM_ERROR_NOT_IMPLEMENTED;
418         }
419
420         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
421         if (!layer_buffer) {
422                 _pthread_mutex_unlock(&private_display->lock);
423                 TDM_ERR("alloc failed");
424                 return TDM_ERROR_OUT_OF_MEMORY;
425         }
426         LIST_INITHEAD(&layer_buffer->link);
427
428         ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
429         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
430
431         /* dump buffer */
432         if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
433                 _tdm_layer_dump_buffer(layer, buffer);
434
435         if (ret == TDM_ERROR_NONE) {
436                 if (private_layer->waiting_buffer)
437                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
438
439                 private_layer->waiting_buffer = layer_buffer;
440                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(buffer);
441                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
442                         TDM_INFO("layer(%p) waiting_buffer(%p)",
443                                          private_layer, private_layer->waiting_buffer->buffer);
444         } else
445                 _tdm_layer_free_buffer(private_layer, layer_buffer);
446
447         _pthread_mutex_unlock(&private_display->lock);
448
449         return ret;
450 }
451
452 EXTERN tdm_error
453 tdm_layer_unset_buffer(tdm_layer *layer)
454 {
455         tdm_func_layer *func_layer;
456         LAYER_FUNC_ENTRY();
457
458         _pthread_mutex_lock(&private_display->lock);
459
460         func_layer = &private_display->func_layer;
461
462         _tdm_layer_free_all_buffers(private_layer);
463
464         private_layer->usable = 1;
465
466         if (private_layer->usable)
467                 TDM_INFO("layer(%p) now usable", private_layer);
468
469         if (!func_layer->layer_unset_buffer) {
470                 _pthread_mutex_unlock(&private_display->lock);
471                 TDM_ERR("not implemented!!");
472                 return TDM_ERROR_NOT_IMPLEMENTED;
473         }
474
475         ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
476         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
477
478         _pthread_mutex_unlock(&private_display->lock);
479
480         return ret;
481 }
482
483 INTERN void
484 tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
485 {
486         tdm_private_output *private_output = private_layer->private_output;
487         tdm_private_display *private_display = private_output->private_display;
488
489         if (private_display->print_fps) {
490                 double curr = tdm_helper_get_time();
491                 if (private_layer->fps_stamp == 0) {
492                         private_layer->fps_stamp = curr;
493                 } else if ((curr - private_layer->fps_stamp) > 1.0) {
494                         TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
495                         private_layer->fps_count = 0;
496                         private_layer->fps_stamp = curr;
497                 } else
498                         private_layer->fps_count++;
499         } else if (private_layer->fps_stamp != 0) {
500                 private_layer->fps_stamp = 0;
501                 private_layer->fps_count = 0;
502         }
503
504         if (private_layer->showing_buffer)
505                 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
506
507         private_layer->showing_buffer = *committed_buffer;
508         *committed_buffer = NULL;
509
510         if (tdm_debug_module & TDM_DEBUG_BUFFER)
511                 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
512                                  private_layer, *committed_buffer,
513                                  (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
514 }
515
516 static void
517 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
518                                                          unsigned int tv_sec, unsigned int tv_usec)
519 {
520         tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
521         tdm_private_display *private_display;
522         struct list_head clone_list, pending_clone_list;
523         tdm_error ret;
524
525         private_display = private_output->private_display;
526
527         private_output->layer_waiting_vblank = 0;
528
529         LIST_INITHEAD(&clone_list);
530         LIST_INITHEAD(&pending_clone_list);
531
532         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
533                 LIST_DEL(&lm->link);
534                 lm->private_layer->committing = 0;
535                 LIST_ADDTAIL(&lm->link, &clone_list);
536         }
537
538         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
539                 LIST_DEL(&lm->link);
540                 lm->private_layer->committing = 0;
541                 LIST_ADDTAIL(&lm->link, &pending_clone_list);
542         }
543
544         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
545                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
546                         TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
547                                          lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
548
549                 LIST_DEL(&lm->link);
550                 tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
551                 _pthread_mutex_unlock(&private_display->lock);
552                 if (lm->func)
553                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
554                 _pthread_mutex_lock(&private_display->lock);
555                 if (lm->committed_buffer)
556                         _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
557                 free(lm);
558         }
559
560         if (LIST_IS_EMPTY(&pending_clone_list))
561                 return;
562
563         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
564
565         ret = tdm_output_commit_internal(private_output, 0, NULL, NULL);
566         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
567
568         if (tdm_debug_module & TDM_DEBUG_COMMIT)
569                 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
570
571         if (private_output->current_dpms_value == TDM_OUTPUT_DPMS_ON) {
572                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
573                 if (!private_output->layer_waiting_vblank) {
574                         _pthread_mutex_unlock(&private_display->lock);
575                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
576                         _pthread_mutex_lock(&private_display->lock);
577                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
578                         private_output->layer_waiting_vblank = 1;
579                 }
580         }
581
582         if (tdm_debug_module & TDM_DEBUG_COMMIT)
583                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
584
585         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
586                 LIST_DEL(&lm->link);
587                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
588         }
589
590         if (private_output->current_dpms_value != TDM_OUTPUT_DPMS_ON) {
591                 TDM_WRN("TDM_OUTPUT_DPMS_OFF. Directly call vblank callback.");
592                 _pthread_mutex_unlock(&private_display->lock);
593                 _tdm_layer_cb_wait_vblank(private_output->vblank, 0, 0, 0, 0, private_output);
594                 _pthread_mutex_lock(&private_display->lock);
595         }
596
597         return;
598 wait_failed:
599         /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
600          * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
601          * the layer commit handler MUST be called.
602          */
603         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
604                 TDM_WRN("Directly call layer commit handlers: ret(%d)\n", ret);
605                 LIST_DEL(&lm->link);
606                 _pthread_mutex_unlock(&private_display->lock);
607                 if (lm->func)
608                         lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
609                 _pthread_mutex_lock(&private_display->lock);
610                 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
611                 free(lm);
612         }
613
614         return;
615 }
616
617 static void
618 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
619                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
620 {
621         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
622         tdm_private_layer_commit_handler *lm = NULL;
623         tdm_private_display *private_display;
624         tdm_private_output *private_output = output;
625         tdm_private_layer *private_layer;
626         int found = 0;
627
628         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
629
630         private_display = private_output->private_display;
631
632         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
633                 if (layer_commit_handler == lm) {
634                         found = 1;
635                         break;
636                 }
637         }
638
639         if (!found)
640                 return;
641
642         private_layer = layer_commit_handler->private_layer;
643
644         if (tdm_debug_module & TDM_DEBUG_COMMIT)
645                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
646                                  private_layer, private_output->pipe, layer_commit_handler);
647
648         _pthread_mutex_lock(&private_display->lock);
649
650         tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
651
652         if (layer_commit_handler->func) {
653                 _pthread_mutex_unlock(&private_display->lock);
654                 layer_commit_handler->func(private_output, sequence,
655                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
656                 _pthread_mutex_lock(&private_display->lock);
657         }
658
659         LIST_DEL(&layer_commit_handler->link);
660         free(layer_commit_handler);
661
662         _pthread_mutex_unlock(&private_display->lock);
663 }
664
665 static void
666 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
667                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
668 {
669         tdm_private_output *private_output = user_data;
670         tdm_private_display *private_display;
671
672         TDM_RETURN_IF_FAIL(private_output != NULL);
673
674         private_display = private_output->private_display;
675
676         _pthread_mutex_lock(&private_display->lock);
677
678         if (tdm_debug_module & TDM_DEBUG_COMMIT)
679                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
680
681         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
682
683         _pthread_mutex_unlock(&private_display->lock);
684 }
685
686 static unsigned int
687 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
688 {
689         tdm_private_layer *private_layer = NULL;
690         unsigned int count = 0;
691
692         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
693                 if (!private_layer->usable)
694                         count++;
695         }
696
697         return count;
698 }
699
700 static int
701 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
702 {
703         tdm_private_output *private_output = private_layer->private_output;
704         tdm_private_display *private_display = private_output->private_display;
705
706         if (private_display->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) == 1) {
707                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
708                         TDM_INFO("layer(%p) commit: 1 layer", private_layer);
709                 return 1;
710         }
711
712         if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
713                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
714                         TDM_INFO("layer(%p) commit: non previous commit", private_layer);
715                 return 1;
716         }
717
718         return 0;
719 }
720
721 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
722  * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
723  * the layer commit handler MUST be called.
724  */
725 static tdm_error
726 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
727 {
728         tdm_private_layer_commit_handler *layer_commit_handler;
729         LAYER_FUNC_ENTRY();
730
731         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
732         if (!layer_commit_handler) {
733                 TDM_ERR("failed: alloc memory");
734                 return TDM_ERROR_OUT_OF_MEMORY;
735         }
736
737         if (tdm_debug_module & TDM_DEBUG_COMMIT)
738                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
739
740         LIST_INITHEAD(&layer_commit_handler->link);
741         layer_commit_handler->private_layer = private_layer;
742         layer_commit_handler->func = func;
743         layer_commit_handler->user_data = user_data;
744
745         layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
746         private_layer->waiting_buffer = NULL;
747
748         if (tdm_debug_module & TDM_DEBUG_BUFFER)
749                 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
750                                  private_layer, private_layer->waiting_buffer,
751                                  (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
752
753         if (!private_display->commit_per_vblank) {
754                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
755
756                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
757                 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
758                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
759
760                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
761                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
762         } else {
763                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
764
765                 if (private_layer->committing)
766                         TDM_WRN("layer(%d) too many commit", private_layer->index);
767                 else
768                         private_layer->committing = 1;
769
770                 if (_tdm_layer_commit_possible(private_layer)) {
771                         /* add to layer_commit_handler_list */
772                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
773                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
774                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
775
776                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
777                                 TDM_INFO("layer(%p) commit: output", private_layer);
778                 } else {
779                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
780                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
781
782                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
783                                 TDM_INFO("layer(%p) commit: pending", private_layer);
784                 }
785
786                 if (!private_output->vblank) {
787                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
788                         _pthread_mutex_unlock(&private_display->lock);
789                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
790                         _pthread_mutex_lock(&private_display->lock);
791                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
792                 }
793
794                 if (!private_output->layer_waiting_vblank) {
795                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
796                         _pthread_mutex_unlock(&private_display->lock);
797                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
798                         _pthread_mutex_lock(&private_display->lock);
799                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
800                         private_output->layer_waiting_vblank = 1;
801
802                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
803                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
804                 }
805         }
806
807         return ret;
808
809 commit_failed:
810         if (layer_commit_handler) {
811                 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
812                 LIST_DEL(&layer_commit_handler->link);
813                 free(layer_commit_handler);
814         }
815         return ret;
816 }
817
818 EXTERN tdm_error
819 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
820 {
821         LAYER_FUNC_ENTRY();
822
823         _pthread_mutex_lock(&private_display->lock);
824
825         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
826                 if (!private_display->commit_per_vblank)
827                         private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
828                 else
829                         private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
830         }
831
832         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
833                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
834                                 tdm_dpms_str(private_output->current_dpms_value));
835                 _pthread_mutex_unlock(&private_display->lock);
836                 return TDM_ERROR_DPMS_OFF;
837         }
838
839         ret = _tdm_layer_commit(private_layer, func, user_data);
840
841         _pthread_mutex_unlock(&private_display->lock);
842
843         return ret;
844 }
845
846 EXTERN tdm_error
847 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
848 {
849         LAYER_FUNC_ENTRY();
850
851         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
852
853         _pthread_mutex_lock(&private_display->lock);
854
855         *committing = private_layer->committing;
856
857         _pthread_mutex_unlock(&private_display->lock);
858
859         return ret;
860 }
861
862 EXTERN tbm_surface_h
863 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
864 {
865         tbm_surface_h buffer;
866         LAYER_FUNC_ENTRY_ERROR();
867
868         _pthread_mutex_lock(&private_display->lock);
869
870         if (error)
871                 *error = TDM_ERROR_NONE;
872
873         if (private_layer->showing_buffer) {
874                 buffer = private_layer->showing_buffer->buffer;
875         } else {
876                 if (error)
877                         *error = TDM_ERROR_OPERATION_FAILED;
878                 _pthread_mutex_unlock(&private_display->lock);
879                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
880                 return NULL;
881         }
882         _pthread_mutex_unlock(&private_display->lock);
883
884         return buffer;
885 }
886
887 static void
888 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
889 {
890         TDM_RETURN_IF_FAIL(data != NULL);
891         tdm_layer *layer = data;
892         tdm_func_layer *func_layer;
893         tbm_surface_h surface = NULL;
894         tdm_private_layer_buffer *layer_buffer;
895         LAYER_FUNC_ENTRY_VOID_RETURN();
896
897         _pthread_mutex_lock(&private_display->lock);
898
899         func_layer = &private_display->func_layer;
900         if (!func_layer->layer_set_buffer) {
901                 _pthread_mutex_unlock(&private_display->lock);
902                 return;
903         }
904
905         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
906         if (!layer_buffer) {
907                 _pthread_mutex_unlock(&private_display->lock);
908                 TDM_ERR("alloc failed");
909                 return;
910         }
911         LIST_INITHEAD(&layer_buffer->link);
912
913         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
914                 surface == NULL) {
915                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
916                                 private_layer, surface);
917                 _pthread_mutex_unlock(&private_display->lock);
918                 free(layer_buffer);
919                 return;
920         }
921
922         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
923         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
924
925         if (ret == TDM_ERROR_NONE) {
926                 if (private_layer->waiting_buffer) {
927                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
928                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
929                 }
930
931                 private_layer->waiting_buffer = layer_buffer;
932                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
933
934                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
935                         TDM_INFO("layer(%p) waiting_buffer(%p)",
936                                          private_layer, private_layer->waiting_buffer->buffer);
937
938                 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
939                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
940                         if (ret != TDM_ERROR_NONE)
941                                 TDM_ERR("tdm_output_commit_internal() is fail");
942                 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
943                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
944                         if (ret != TDM_ERROR_NONE)
945                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
946                 } else {
947                         TDM_NEVER_GET_HERE();
948                 }
949         } else
950                 _tdm_layer_free_buffer(private_layer, layer_buffer);
951
952         _pthread_mutex_unlock(&private_display->lock);
953 }
954
955 static void
956 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
957 {
958         TDM_RETURN_IF_FAIL(data != NULL);
959         tdm_layer *layer = data;
960         LAYER_FUNC_ENTRY_VOID_RETURN();
961         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
962
963         _pthread_mutex_lock(&private_display->lock);
964
965         private_layer->buffer_queue = NULL;
966
967         _tdm_layer_free_all_buffers(private_layer);
968
969         _pthread_mutex_unlock(&private_display->lock);
970 }
971
972 EXTERN tdm_error
973 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
974 {
975         tdm_func_layer *func_layer;
976         LAYER_FUNC_ENTRY();
977
978         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
979
980         _pthread_mutex_lock(&private_display->lock);
981
982         func_layer = &private_display->func_layer;
983
984         if (private_layer->usable)
985                 TDM_INFO("layer(%p) not usable", private_layer);
986
987         private_layer->usable = 0;
988
989         if (!func_layer->layer_set_buffer) {
990                 _pthread_mutex_unlock(&private_display->lock);
991                 TDM_ERR("not implemented!!");
992                 return TDM_ERROR_NOT_IMPLEMENTED;
993         }
994
995         if (buffer_queue == private_layer->buffer_queue) {
996                 _pthread_mutex_unlock(&private_display->lock);
997                 return TDM_ERROR_NONE;
998         }
999
1000         if (private_layer->waiting_buffer) {
1001                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1002                 private_layer->waiting_buffer = NULL;
1003
1004                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1005                         TDM_INFO("layer(%p) waiting_buffer(%p)",
1006                                          private_layer, private_layer->waiting_buffer);
1007         }
1008
1009         private_layer->buffer_queue = buffer_queue;
1010         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1011                                                                                 _tbm_layer_queue_acquirable_cb,
1012                                                                                 private_layer);
1013         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1014                                                                          _tbm_layer_queue_destroy_cb,
1015                                                                          private_layer);
1016         _pthread_mutex_unlock(&private_display->lock);
1017
1018         return ret;
1019 }
1020
1021 EXTERN tdm_error
1022 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1023 {
1024         return tdm_layer_unset_buffer(layer);
1025 }
1026
1027 EXTERN tdm_error
1028 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1029 {
1030         LAYER_FUNC_ENTRY();
1031
1032         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1033
1034         _pthread_mutex_lock(&private_display->lock);
1035
1036         *usable = private_layer->usable;
1037
1038         _pthread_mutex_unlock(&private_display->lock);
1039
1040         return ret;
1041 }
1042
1043 EXTERN tdm_error
1044 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1045 {
1046         tdm_func_layer *func_layer;
1047         LAYER_FUNC_ENTRY();
1048
1049         _pthread_mutex_lock(&private_display->lock);
1050
1051         func_layer = &private_display->func_layer;
1052
1053         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1054                 TDM_ERR("layer(%p) is not video layer", private_layer);
1055                 _pthread_mutex_unlock(&private_display->lock);
1056                 return TDM_ERROR_INVALID_PARAMETER;
1057         }
1058
1059         if (!func_layer->layer_set_video_pos) {
1060                 _pthread_mutex_unlock(&private_display->lock);
1061                 TDM_ERR("not implemented!!");
1062                 return TDM_ERROR_NOT_IMPLEMENTED;
1063         }
1064
1065         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1066
1067         _pthread_mutex_unlock(&private_display->lock);
1068
1069         return ret;
1070 }
1071
1072 EXTERN tdm_capture *
1073 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1074 {
1075         tdm_capture *capture = NULL;
1076
1077         LAYER_FUNC_ENTRY_ERROR();
1078
1079         _pthread_mutex_lock(&private_display->lock);
1080
1081         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1082
1083         _pthread_mutex_unlock(&private_display->lock);
1084
1085         return capture;
1086 }
1087
1088 EXTERN tdm_error
1089 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1090 {
1091         tdm_func_layer *func_layer;
1092         LAYER_FUNC_ENTRY();
1093
1094         _pthread_mutex_lock(&private_display->lock);
1095
1096         func_layer = &private_display->func_layer;
1097
1098         if (!func_layer->layer_get_buffer_flags) {
1099                 _pthread_mutex_unlock(&private_display->lock);
1100                 TDM_ERR("not implemented!!");
1101                 return TDM_ERROR_NOT_IMPLEMENTED;
1102         }
1103
1104         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1105
1106         _pthread_mutex_unlock(&private_display->lock);
1107
1108         return ret;
1109 }