display: separate output & layer part from display
[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         /* tdm_vblank APIs is for server. it should be called in unlock status*/
572         if (!private_output->layer_waiting_vblank) {
573                 _pthread_mutex_unlock(&private_display->lock);
574                 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
575                 _pthread_mutex_lock(&private_display->lock);
576                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
577                 private_output->layer_waiting_vblank = 1;
578         }
579
580         if (tdm_debug_module & TDM_DEBUG_COMMIT)
581                 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
582
583         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
584                 LIST_DEL(&lm->link);
585                 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
586         }
587
588         return;
589 wait_failed:
590         LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
591                 LIST_DEL(&lm->link);
592                 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
593                 free(lm);
594         }
595         return;
596 }
597
598 static void
599 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
600                                                         unsigned int tv_sec, unsigned int tv_usec, void *user_data)
601 {
602         tdm_private_layer_commit_handler *layer_commit_handler = user_data;
603         tdm_private_layer_commit_handler *lm = NULL;
604         tdm_private_display *private_display;
605         tdm_private_output *private_output = output;
606         tdm_private_layer *private_layer;
607         int found = 0;
608
609         TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
610
611         private_display = private_output->private_display;
612
613         LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
614                 if (layer_commit_handler == lm) {
615                         found = 1;
616                         break;
617                 }
618         }
619
620         if (!found)
621                 return;
622
623         private_layer = layer_commit_handler->private_layer;
624
625         if (tdm_debug_module & TDM_DEBUG_COMMIT)
626                 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
627                                  private_layer, private_output->pipe, layer_commit_handler);
628
629         _pthread_mutex_lock(&private_display->lock);
630
631         tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
632
633         if (layer_commit_handler->func) {
634                 _pthread_mutex_unlock(&private_display->lock);
635                 layer_commit_handler->func(private_output, sequence,
636                                                                    tv_sec, tv_usec, layer_commit_handler->user_data);
637                 _pthread_mutex_lock(&private_display->lock);
638         }
639
640         LIST_DEL(&layer_commit_handler->link);
641         free(layer_commit_handler);
642
643         _pthread_mutex_unlock(&private_display->lock);
644 }
645
646 static void
647 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
648                                                   unsigned int tv_sec, unsigned int tv_usec, void *user_data)
649 {
650         tdm_private_output *private_output = user_data;
651         tdm_private_display *private_display;
652
653         TDM_RETURN_IF_FAIL(private_output != NULL);
654
655         private_display = private_output->private_display;
656
657         _pthread_mutex_lock(&private_display->lock);
658
659         if (tdm_debug_module & TDM_DEBUG_COMMIT)
660                 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
661
662         _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
663
664         _pthread_mutex_unlock(&private_display->lock);
665 }
666
667 static unsigned int
668 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
669 {
670         tdm_private_layer *private_layer = NULL;
671         unsigned int count = 0;
672
673         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
674                 if (!private_layer->usable)
675                         count++;
676         }
677
678         return count;
679 }
680
681 static int
682 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
683 {
684         tdm_private_output *private_output = private_layer->private_output;
685         tdm_private_display *private_display = private_output->private_display;
686
687         if (private_display->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) == 1) {
688                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
689                         TDM_INFO("layer(%p) commit: 1 layer", private_layer);
690                 return 1;
691         }
692
693         if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
694                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
695                         TDM_INFO("layer(%p) commit: non previous commit", private_layer);
696                 return 1;
697         }
698
699         return 0;
700 }
701
702 static tdm_error
703 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
704 {
705         tdm_private_layer_commit_handler *layer_commit_handler;
706         LAYER_FUNC_ENTRY();
707
708         layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
709         if (!layer_commit_handler) {
710                 TDM_ERR("failed: alloc memory");
711                 return TDM_ERROR_OUT_OF_MEMORY;
712         }
713
714         if (tdm_debug_module & TDM_DEBUG_COMMIT)
715                 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
716
717         LIST_INITHEAD(&layer_commit_handler->link);
718         layer_commit_handler->private_layer = private_layer;
719         layer_commit_handler->func = func;
720         layer_commit_handler->user_data = user_data;
721
722         layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
723         private_layer->waiting_buffer = NULL;
724
725         if (tdm_debug_module & TDM_DEBUG_BUFFER)
726                 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
727                                  private_layer, private_layer->waiting_buffer,
728                                  (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
729
730         if (!private_display->commit_per_vblank) {
731                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
732
733                 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
734                 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
735                 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
736
737                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
738                         TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
739         } else {
740                 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
741
742                 if (private_layer->committing)
743                         TDM_WRN("layer(%d) too many commit", private_layer->index);
744                 else
745                         private_layer->committing = 1;
746
747                 if (_tdm_layer_commit_possible(private_layer)) {
748                         /* add to layer_commit_handler_list */
749                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
750                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
751                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
752
753                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
754                                 TDM_INFO("layer(%p) commit: output", private_layer);
755                 } else {
756                         /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
757                         LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
758
759                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
760                                 TDM_INFO("layer(%p) commit: pending", private_layer);
761                 }
762
763                 if (!private_output->vblank) {
764                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
765                         _pthread_mutex_unlock(&private_display->lock);
766                         private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
767                         _pthread_mutex_lock(&private_display->lock);
768                         TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
769                 }
770
771                 if (!private_output->layer_waiting_vblank) {
772                         /* tdm_vblank APIs is for server. it should be called in unlock status*/
773                         _pthread_mutex_unlock(&private_display->lock);
774                         ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
775                         _pthread_mutex_lock(&private_display->lock);
776                         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
777                         private_output->layer_waiting_vblank = 1;
778
779                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
780                                 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
781                 }
782         }
783
784         return ret;
785
786 commit_failed:
787         if (layer_commit_handler) {
788                 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
789                 LIST_DEL(&layer_commit_handler->link);
790                 free(layer_commit_handler);
791         }
792         return ret;
793 }
794
795 EXTERN tdm_error
796 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
797 {
798         LAYER_FUNC_ENTRY();
799
800         _pthread_mutex_lock(&private_display->lock);
801
802         if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
803                 if (!private_display->commit_per_vblank)
804                         private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
805                 else
806                         private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
807         }
808
809         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
810                 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
811                                 tdm_dpms_str(private_output->current_dpms_value));
812                 _pthread_mutex_unlock(&private_display->lock);
813                 return TDM_ERROR_DPMS_OFF;
814         }
815
816         ret = _tdm_layer_commit(private_layer, func, user_data);
817
818         _pthread_mutex_unlock(&private_display->lock);
819
820         return ret;
821 }
822
823 EXTERN tdm_error
824 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
825 {
826         LAYER_FUNC_ENTRY();
827
828         TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
829
830         _pthread_mutex_lock(&private_display->lock);
831
832         *committing = private_layer->committing;
833
834         _pthread_mutex_unlock(&private_display->lock);
835
836         return ret;
837 }
838
839 EXTERN tbm_surface_h
840 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
841 {
842         tbm_surface_h buffer;
843         LAYER_FUNC_ENTRY_ERROR();
844
845         _pthread_mutex_lock(&private_display->lock);
846
847         if (error)
848                 *error = TDM_ERROR_NONE;
849
850         if (private_layer->showing_buffer) {
851                 buffer = private_layer->showing_buffer->buffer;
852         } else {
853                 if (error)
854                         *error = TDM_ERROR_OPERATION_FAILED;
855                 _pthread_mutex_unlock(&private_display->lock);
856                 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
857                 return NULL;
858         }
859         _pthread_mutex_unlock(&private_display->lock);
860
861         return buffer;
862 }
863
864 static void
865 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
866 {
867         TDM_RETURN_IF_FAIL(data != NULL);
868         tdm_layer *layer = data;
869         tdm_func_layer *func_layer;
870         tbm_surface_h surface = NULL;
871         tdm_private_layer_buffer *layer_buffer;
872         LAYER_FUNC_ENTRY_VOID_RETURN();
873
874         _pthread_mutex_lock(&private_display->lock);
875
876         func_layer = &private_display->func_layer;
877         if (!func_layer->layer_set_buffer) {
878                 _pthread_mutex_unlock(&private_display->lock);
879                 return;
880         }
881
882         layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
883         if (!layer_buffer) {
884                 _pthread_mutex_unlock(&private_display->lock);
885                 TDM_ERR("alloc failed");
886                 return;
887         }
888         LIST_INITHEAD(&layer_buffer->link);
889
890         if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
891                 surface == NULL) {
892                 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
893                                 private_layer, surface);
894                 _pthread_mutex_unlock(&private_display->lock);
895                 free(layer_buffer);
896                 return;
897         }
898
899         ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
900         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
901
902         if (ret == TDM_ERROR_NONE) {
903                 if (private_layer->waiting_buffer) {
904                         TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
905                         _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
906                 }
907
908                 private_layer->waiting_buffer = layer_buffer;
909                 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
910
911                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
912                         TDM_INFO("layer(%p) waiting_buffer(%p)",
913                                          private_layer, private_layer->waiting_buffer->buffer);
914
915                 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
916                         ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
917                         if (ret != TDM_ERROR_NONE)
918                                 TDM_ERR("tdm_output_commit_internal() is fail");
919                 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
920                         ret = _tdm_layer_commit(private_layer, NULL, NULL);
921                         if (ret != TDM_ERROR_NONE)
922                                 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
923                 } else {
924                         TDM_NEVER_GET_HERE();
925                 }
926         } else
927                 _tdm_layer_free_buffer(private_layer, layer_buffer);
928
929         _pthread_mutex_unlock(&private_display->lock);
930 }
931
932 static void
933 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
934 {
935         TDM_RETURN_IF_FAIL(data != NULL);
936         tdm_layer *layer = data;
937         LAYER_FUNC_ENTRY_VOID_RETURN();
938         TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
939
940         _pthread_mutex_lock(&private_display->lock);
941
942         private_layer->buffer_queue = NULL;
943
944         _tdm_layer_free_all_buffers(private_layer);
945
946         _pthread_mutex_unlock(&private_display->lock);
947 }
948
949 EXTERN tdm_error
950 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
951 {
952         tdm_func_layer *func_layer;
953         LAYER_FUNC_ENTRY();
954
955         TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
956
957         _pthread_mutex_lock(&private_display->lock);
958
959         func_layer = &private_display->func_layer;
960
961         if (private_layer->usable)
962                 TDM_INFO("layer(%p) not usable", private_layer);
963
964         private_layer->usable = 0;
965
966         if (!func_layer->layer_set_buffer) {
967                 _pthread_mutex_unlock(&private_display->lock);
968                 TDM_ERR("not implemented!!");
969                 return TDM_ERROR_NOT_IMPLEMENTED;
970         }
971
972         if (buffer_queue == private_layer->buffer_queue) {
973                 _pthread_mutex_unlock(&private_display->lock);
974                 return TDM_ERROR_NONE;
975         }
976
977         if (private_layer->waiting_buffer) {
978                 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
979                 private_layer->waiting_buffer = NULL;
980
981                 if (tdm_debug_module & TDM_DEBUG_BUFFER)
982                         TDM_INFO("layer(%p) waiting_buffer(%p)",
983                                          private_layer, private_layer->waiting_buffer);
984         }
985
986         private_layer->buffer_queue = buffer_queue;
987         tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
988                                                                                 _tbm_layer_queue_acquirable_cb,
989                                                                                 private_layer);
990         tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
991                                                                          _tbm_layer_queue_destroy_cb,
992                                                                          private_layer);
993         _pthread_mutex_unlock(&private_display->lock);
994
995         return ret;
996 }
997
998 EXTERN tdm_error
999 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1000 {
1001         return tdm_layer_unset_buffer(layer);
1002 }
1003
1004 EXTERN tdm_error
1005 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1006 {
1007         LAYER_FUNC_ENTRY();
1008
1009         TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1010
1011         _pthread_mutex_lock(&private_display->lock);
1012
1013         *usable = private_layer->usable;
1014
1015         _pthread_mutex_unlock(&private_display->lock);
1016
1017         return ret;
1018 }
1019
1020 EXTERN tdm_error
1021 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1022 {
1023         tdm_func_layer *func_layer;
1024         LAYER_FUNC_ENTRY();
1025
1026         _pthread_mutex_lock(&private_display->lock);
1027
1028         func_layer = &private_display->func_layer;
1029
1030         if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1031                 TDM_ERR("layer(%p) is not video layer", private_layer);
1032                 _pthread_mutex_unlock(&private_display->lock);
1033                 return TDM_ERROR_INVALID_PARAMETER;
1034         }
1035
1036         if (!func_layer->layer_set_video_pos) {
1037                 _pthread_mutex_unlock(&private_display->lock);
1038                 TDM_ERR("not implemented!!");
1039                 return TDM_ERROR_NOT_IMPLEMENTED;
1040         }
1041
1042         ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1043
1044         _pthread_mutex_unlock(&private_display->lock);
1045
1046         return ret;
1047 }
1048
1049 EXTERN tdm_capture *
1050 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1051 {
1052         tdm_capture *capture = NULL;
1053
1054         LAYER_FUNC_ENTRY_ERROR();
1055
1056         _pthread_mutex_lock(&private_display->lock);
1057
1058         capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1059
1060         _pthread_mutex_unlock(&private_display->lock);
1061
1062         return capture;
1063 }
1064
1065 EXTERN tdm_error
1066 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1067 {
1068         tdm_func_layer *func_layer;
1069         LAYER_FUNC_ENTRY();
1070
1071         _pthread_mutex_lock(&private_display->lock);
1072
1073         func_layer = &private_display->func_layer;
1074
1075         if (!func_layer->layer_get_buffer_flags) {
1076                 _pthread_mutex_unlock(&private_display->lock);
1077                 TDM_ERR("not implemented!!");
1078                 return TDM_ERROR_NOT_IMPLEMENTED;
1079         }
1080
1081         ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1082
1083         _pthread_mutex_unlock(&private_display->lock);
1084
1085         return ret;
1086 }