1 /**************************************************************************
5 * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
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.
34 **************************************************************************/
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
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
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
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
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 static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
83 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
84 static void _tdm_layer_reset_pending_data(tdm_private_layer *private_layer);
87 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
93 str = getenv("TDM_HWC");
96 hwc_enable = strtol(str, NULL, 10);
98 /* an ecore_drm related fix: sorry... when ecore_drm refuses to use
99 * tdm_layer we'll remove this code */
102 *capabilities = TDM_LAYER_CAPABILITY_PRIMARY;
103 return TDM_ERROR_NONE;
108 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
110 _pthread_mutex_lock(&private_display->lock);
112 *capabilities = private_layer->caps.capabilities;
114 _pthread_mutex_unlock(&private_display->lock);
120 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count)
124 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
125 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
127 _pthread_mutex_lock(&private_display->lock);
129 *formats = (const tbm_format *)private_layer->caps.formats;
130 *count = private_layer->caps.format_count;
132 _pthread_mutex_unlock(&private_display->lock);
138 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count)
142 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
143 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
145 _pthread_mutex_lock(&private_display->lock);
147 *props = (const tdm_prop *)private_layer->caps.props;
148 *count = private_layer->caps.prop_count;
150 _pthread_mutex_unlock(&private_display->lock);
156 tdm_layer_get_zpos(tdm_layer *layer, int *zpos)
160 TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
162 _pthread_mutex_lock(&private_display->lock);
164 *zpos = private_layer->caps.zpos;
166 _pthread_mutex_unlock(&private_display->lock);
172 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
174 tdm_func_layer *func_layer;
177 _pthread_mutex_lock(&private_display->lock);
179 func_layer = &private_display->func_layer;
181 if (private_layer->usable)
182 TDM_INFO("layer(%d) not usable", private_layer->index);
184 private_layer->usable = 0;
186 if (!func_layer->layer_set_property) {
187 _pthread_mutex_unlock(&private_display->lock);
188 TDM_ERR("not implemented!!");
189 return TDM_ERROR_NOT_IMPLEMENTED;
192 ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
194 _pthread_mutex_unlock(&private_display->lock);
200 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
202 tdm_func_layer *func_layer;
205 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
207 _pthread_mutex_lock(&private_display->lock);
209 func_layer = &private_display->func_layer;
211 if (!func_layer->layer_get_property) {
212 _pthread_mutex_unlock(&private_display->lock);
213 TDM_ERR("not implemented!!");
214 return TDM_ERROR_NOT_IMPLEMENTED;
217 ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
219 _pthread_mutex_unlock(&private_display->lock);
225 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
227 tdm_func_layer *func_layer;
232 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
234 _pthread_mutex_lock(&private_display->lock);
236 func_layer = &private_display->func_layer;
238 if (private_layer->usable)
239 TDM_INFO("layer(%p) not usable", private_layer);
241 private_layer->usable = 0;
243 if (!func_layer->layer_set_info) {
244 _pthread_mutex_unlock(&private_display->lock);
245 TDM_ERR("not implemented!!");
246 return TDM_ERROR_NOT_IMPLEMENTED;
249 if (info->src_config.format)
250 snprintf(fmtstr, 128, "%c%c%c%c", FOURCC_STR(info->src_config.format));
252 snprintf(fmtstr, 128, "NONE");
254 TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %s) dst(%d,%d %dx%d) trans(%d)",
255 private_layer, info->src_config.size.h, info->src_config.size.v,
256 info->src_config.pos.x, info->src_config.pos.y,
257 info->src_config.pos.w, info->src_config.pos.h,
259 info->dst_pos.x, info->dst_pos.y,
260 info->dst_pos.w, info->dst_pos.h,
263 private_layer->pending_info_changed = 1;
264 private_layer->pending_info = *info;
266 _pthread_mutex_unlock(&private_display->lock);
272 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
274 tdm_func_layer *func_layer;
277 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
279 _pthread_mutex_lock(&private_display->lock);
281 func_layer = &private_display->func_layer;
283 if (!func_layer->layer_get_info) {
284 _pthread_mutex_unlock(&private_display->lock);
285 TDM_ERR("not implemented!!");
286 return TDM_ERROR_NOT_IMPLEMENTED;
289 ret = func_layer->layer_get_info(private_layer->layer_backend, info);
291 _pthread_mutex_unlock(&private_display->lock);
297 _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer)
299 tdm_private_layer *private_layer = (tdm_private_layer*)layer;
300 tdm_private_output *private_output = private_layer->private_output;
302 char fname[PATH_MAX], bufs[PATH_MAX];
303 int zpos, len = PATH_MAX;
304 tdm_private_layer *l = NULL;
308 pipe = private_output->pipe;
309 zpos = private_layer->caps.zpos;
312 LIST_FOR_EACH_ENTRY(l, &private_output->layer_list, link) {
313 if (!l->showing_buffer)
315 TDM_SNPRINTF(p, remain, "_%p", l->showing_buffer->buffer);
318 snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d%s", pipe, zpos, bufs);
320 tbm_surface_internal_dump_buffer(buffer, fname);
321 TDM_DBG("%s dump excute", fname);
327 _tdm_layer_free_buffer(tdm_private_layer *private_layer, tdm_private_layer_buffer *layer_buffer)
329 tdm_private_display *private_display;
334 private_display = private_layer->private_output->private_display;
336 LIST_DEL(&layer_buffer->link);
337 if (layer_buffer->buffer) {
338 _pthread_mutex_unlock(&private_display->lock);
339 tdm_buffer_unref_backend(layer_buffer->buffer);
340 if (private_layer->buffer_queue)
341 tbm_surface_queue_release(private_layer->buffer_queue, layer_buffer->buffer);
342 _pthread_mutex_lock(&private_display->lock);
348 _tdm_layer_free_all_buffers(tdm_private_layer *private_layer)
350 tdm_private_output *private_output = private_layer->private_output;
351 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
352 struct list_head clone_list;
354 LIST_INITHEAD(&clone_list);
356 _tdm_layer_reset_pending_data(private_layer);
358 if (private_layer->waiting_buffer) {
359 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
360 private_layer->waiting_buffer = NULL;
362 if (tdm_debug_module & TDM_DEBUG_BUFFER)
363 TDM_INFO("layer(%p) waiting_buffer(%p)",
364 private_layer, private_layer->waiting_buffer);
367 if (private_layer->committed_buffer) {
368 _tdm_layer_free_buffer(private_layer, private_layer->committed_buffer);
369 private_layer->committed_buffer = NULL;
371 if (tdm_debug_module & TDM_DEBUG_BUFFER)
372 TDM_INFO("layer(%p) committed_buffer(%p)",
373 private_layer, private_layer->committed_buffer);
376 if (private_layer->showing_buffer) {
377 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
378 private_layer->showing_buffer = NULL;
380 if (tdm_debug_module & TDM_DEBUG_BUFFER)
381 TDM_INFO("layer(%p) showing_buffer(%p)",
382 private_layer, private_layer->showing_buffer);
385 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
386 if (lm->private_layer != private_layer)
389 LIST_ADDTAIL(&lm->link, &clone_list);
392 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
394 tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
395 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
399 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
400 if (lm->private_layer != private_layer)
403 LIST_ADDTAIL(&lm->link, &clone_list);
406 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
408 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
412 if (private_layer->buffer_queue) {
413 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, private_layer);
414 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, private_layer);
415 private_layer->buffer_queue = NULL;
420 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
422 tdm_func_layer *func_layer;
426 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
428 _pthread_mutex_lock(&private_display->lock);
430 if (tdm_debug_dump & TDM_DUMP_FLAG_LAYER &&
431 !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
432 char str[TDM_PATH_LEN];
434 snprintf(str, TDM_PATH_LEN, "layer_%d_%d_%03d",
435 private_output->index, private_layer->index, i++);
436 tdm_helper_dump_buffer_str(buffer, tdm_debug_dump_dir, str);
439 func_layer = &private_display->func_layer;
441 if (private_layer->usable)
442 TDM_INFO("layer(%p) not usable", private_layer);
444 private_layer->usable = 0;
446 if (!func_layer->layer_set_buffer) {
447 _pthread_mutex_unlock(&private_display->lock);
448 TDM_ERR("not implemented!!");
449 return TDM_ERROR_NOT_IMPLEMENTED;
452 private_layer->pending_buffer_changed = 1;
454 if (private_layer->pending_buffer) {
455 tbm_surface_internal_unref(private_layer->pending_buffer);
457 if (tdm_debug_module & TDM_DEBUG_BUFFER)
458 TDM_INFO("layer(%p) pending_buffer(%p) skipped",
459 private_layer, private_layer->pending_buffer);
462 tbm_surface_internal_ref(buffer);
463 private_layer->pending_buffer = buffer;
465 if (tdm_debug_module & TDM_DEBUG_BUFFER)
466 TDM_INFO("layer(%p) pending_buffer(%p)",
467 private_layer, private_layer->pending_buffer);
469 _pthread_mutex_unlock(&private_display->lock);
475 tdm_layer_unset_buffer(tdm_layer *layer)
477 tdm_func_layer *func_layer;
480 _pthread_mutex_lock(&private_display->lock);
482 func_layer = &private_display->func_layer;
484 _tdm_layer_free_all_buffers(private_layer);
486 private_layer->usable = 1;
488 if (private_layer->usable)
489 TDM_INFO("layer(%p) now usable", private_layer);
491 if (!func_layer->layer_unset_buffer) {
492 _pthread_mutex_unlock(&private_display->lock);
493 TDM_ERR("not implemented!!");
494 return TDM_ERROR_NOT_IMPLEMENTED;
497 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
498 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
500 _pthread_mutex_unlock(&private_display->lock);
506 tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer **committed_buffer)
508 tdm_private_output *private_output = private_layer->private_output;
509 tdm_private_display *private_display = private_output->private_display;
511 if (private_display->print_fps) {
512 double curr = tdm_helper_get_time();
513 if (private_layer->fps_stamp == 0) {
514 private_layer->fps_stamp = curr;
515 } else if ((curr - private_layer->fps_stamp) > 1.0) {
516 TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count);
517 private_layer->fps_count = 0;
518 private_layer->fps_stamp = curr;
520 private_layer->fps_count++;
521 } else if (private_layer->fps_stamp != 0) {
522 private_layer->fps_stamp = 0;
523 private_layer->fps_count = 0;
526 if (private_layer->showing_buffer)
527 _tdm_layer_free_buffer(private_layer, private_layer->showing_buffer);
529 private_layer->showing_buffer = *committed_buffer;
530 *committed_buffer = NULL;
532 if (tdm_debug_module & TDM_DEBUG_BUFFER)
533 TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)",
534 private_layer, *committed_buffer,
535 (private_layer->showing_buffer) ? private_layer->showing_buffer->buffer : NULL);
539 _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence,
540 unsigned int tv_sec, unsigned int tv_usec)
542 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
543 tdm_private_display *private_display;
544 struct list_head clone_list, pending_clone_list;
545 tdm_error ret = TDM_ERROR_NONE;
547 private_display = private_output->private_display;
549 private_output->layer_waiting_vblank = 0;
551 LIST_INITHEAD(&clone_list);
552 LIST_INITHEAD(&pending_clone_list);
554 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
556 lm->private_layer->committing = 0;
557 LIST_ADDTAIL(&lm->link, &clone_list);
560 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
562 lm->private_layer->committing = 0;
563 LIST_ADDTAIL(&lm->link, &pending_clone_list);
566 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
567 if (tdm_debug_module & TDM_DEBUG_COMMIT)
568 TDM_INFO("layer(%p) committed. handle(%p) commited_buffer(%p)",
569 lm->private_layer, lm, (lm->committed_buffer) ? lm->committed_buffer->buffer : NULL);
572 tdm_layer_committed(lm->private_layer, &lm->committed_buffer);
573 _pthread_mutex_unlock(&private_display->lock);
575 lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
576 _pthread_mutex_lock(&private_display->lock);
577 if (lm->committed_buffer)
578 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
582 if (LIST_IS_EMPTY(&pending_clone_list))
585 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
587 ret = tdm_output_commit_internal(private_output, 0, NULL, NULL);
588 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
590 if (tdm_debug_module & TDM_DEBUG_COMMIT)
591 TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
593 if (private_output->current_dpms_value == TDM_OUTPUT_DPMS_ON) {
594 /* tdm_vblank APIs is for server. it should be called in unlock status*/
595 if (!private_output->layer_waiting_vblank) {
596 _pthread_mutex_unlock(&private_display->lock);
597 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
598 _pthread_mutex_lock(&private_display->lock);
599 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
600 private_output->layer_waiting_vblank = 1;
604 if (tdm_debug_module & TDM_DEBUG_COMMIT)
605 TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
607 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
609 LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
612 if (private_output->current_dpms_value != TDM_OUTPUT_DPMS_ON) {
613 TDM_WRN("TDM_OUTPUT_DPMS_OFF. Directly call vblank callback.");
614 _pthread_mutex_unlock(&private_display->lock);
615 _tdm_layer_cb_wait_vblank(private_output->vblank, 0, 0, 0, 0, private_output);
616 _pthread_mutex_lock(&private_display->lock);
621 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
622 * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
623 * the layer commit handler MUST be called.
625 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
626 TDM_WRN("Directly call layer commit handlers: ret(%d)\n", ret);
628 _pthread_mutex_unlock(&private_display->lock);
630 lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
631 _pthread_mutex_lock(&private_display->lock);
632 _tdm_layer_free_buffer(lm->private_layer, lm->committed_buffer);
640 _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
641 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
643 tdm_private_layer_commit_handler *layer_commit_handler = user_data;
644 tdm_private_layer_commit_handler *lm = NULL;
645 tdm_private_display *private_display;
646 tdm_private_output *private_output = output;
647 tdm_private_layer *private_layer;
650 TDM_RETURN_IF_FAIL(layer_commit_handler != NULL);
652 private_display = private_output->private_display;
654 LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
655 if (layer_commit_handler == lm) {
664 LIST_DEL(&layer_commit_handler->link);
666 private_layer = layer_commit_handler->private_layer;
668 if (tdm_debug_module & TDM_DEBUG_COMMIT)
669 TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)",
670 private_layer, private_output->pipe, layer_commit_handler);
672 _pthread_mutex_lock(&private_display->lock);
674 tdm_layer_committed(private_layer, &layer_commit_handler->committed_buffer);
676 if (layer_commit_handler->func) {
677 _pthread_mutex_unlock(&private_display->lock);
678 layer_commit_handler->func(private_output, sequence,
679 tv_sec, tv_usec, layer_commit_handler->user_data);
680 _pthread_mutex_lock(&private_display->lock);
683 free(layer_commit_handler);
685 _pthread_mutex_unlock(&private_display->lock);
689 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
690 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
692 tdm_private_output *private_output = user_data;
693 tdm_private_display *private_display;
695 TDM_RETURN_IF_FAIL(private_output != NULL);
697 private_display = private_output->private_display;
699 _pthread_mutex_lock(&private_display->lock);
701 if (tdm_debug_module & TDM_DEBUG_COMMIT)
702 TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe);
704 _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
706 _pthread_mutex_unlock(&private_display->lock);
710 _tdm_lauer_get_output_used_layer_count(tdm_private_output *private_output)
712 tdm_private_layer *private_layer = NULL;
713 unsigned int count = 0;
715 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
716 if (!private_layer->usable)
723 /* commit_per_vblank == 1: we can commit if
724 * - there is no previous commit request
725 * - only 1 layer is used
726 * commit_per_vblank == 2: we can commit if
727 * - there is no previous commit request
730 _tdm_layer_commit_possible(tdm_private_layer *private_layer)
732 tdm_private_output *private_output = private_layer->private_output;
733 tdm_private_display *private_display = private_output->private_display;
735 TDM_RETURN_VAL_IF_FAIL(private_display->commit_per_vblank > 0, 1);
737 /* There is a previous commit request which is not done and displayed on screen yet.
738 * We can't commit at this time.
740 if (!LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) {
741 if (tdm_debug_module & TDM_DEBUG_COMMIT)
742 TDM_INFO("layer(%p) commit: not possible(previous commit)", private_layer);
746 if (private_display->commit_per_vblank == 1 && _tdm_lauer_get_output_used_layer_count(private_output) > 1) {
747 if (tdm_debug_module & TDM_DEBUG_COMMIT)
748 TDM_INFO("layer(%p) commit: not possible(more than 2 layers)", private_layer);
752 if (tdm_debug_module & TDM_DEBUG_COMMIT)
753 TDM_INFO("layer(%p) commit: possible", private_layer);
759 _tdm_layer_reset_pending_data(tdm_private_layer *private_layer)
761 private_layer->pending_info_changed = 0;
762 memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info);
764 private_layer->pending_buffer_changed = 0;
765 if (private_layer->pending_buffer) {
766 tbm_surface_internal_unref(private_layer->pending_buffer);
767 private_layer->pending_buffer = NULL;
772 tdm_layer_commit_pending_data(tdm_private_layer *private_layer)
774 tdm_private_output *private_output = private_layer->private_output;
775 tdm_private_display *private_display = private_output->private_display;
776 tdm_func_layer *func_layer;
777 tdm_error ret = TDM_ERROR_NONE;
779 func_layer = &private_display->func_layer;
781 if (private_layer->pending_info_changed) {
782 ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info);
783 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
786 if (private_layer->pending_buffer_changed) {
787 tdm_private_layer_buffer *layer_buffer;
789 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
790 TDM_GOTO_IF_FAIL(layer_buffer != NULL, done);
792 LIST_INITHEAD(&layer_buffer->link);
794 ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer);
795 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
797 if (tdm_debug_module & TDM_DEBUG_BUFFER)
798 TDM_INFO("layer(%p) pending_buffer(%p) committed",
799 private_layer, private_layer->pending_buffer);
802 if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
803 _tdm_layer_dump_buffer(private_layer, private_layer->pending_buffer);
805 if (ret == TDM_ERROR_NONE) {
806 if (private_layer->waiting_buffer)
807 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
809 private_layer->waiting_buffer = layer_buffer;
810 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer);
811 if (tdm_debug_module & TDM_DEBUG_BUFFER)
812 TDM_INFO("layer(%p) waiting_buffer(%p)",
813 private_layer, private_layer->waiting_buffer->buffer);
815 _tdm_layer_free_buffer(private_layer, layer_buffer);
819 _tdm_layer_reset_pending_data(private_layer);
824 /* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
825 * That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
826 * the layer commit handler MUST be called.
829 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
831 tdm_private_layer_commit_handler *layer_commit_handler;
834 layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
835 if (!layer_commit_handler) {
836 TDM_ERR("failed: alloc memory");
837 return TDM_ERROR_OUT_OF_MEMORY;
840 if (tdm_debug_module & TDM_DEBUG_COMMIT)
841 TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler);
843 LIST_INITHEAD(&layer_commit_handler->link);
844 layer_commit_handler->private_layer = private_layer;
845 layer_commit_handler->func = func;
846 layer_commit_handler->user_data = user_data;
848 layer_commit_handler->committed_buffer = private_layer->waiting_buffer;
849 private_layer->waiting_buffer = NULL;
851 if (tdm_debug_module & TDM_DEBUG_BUFFER)
852 TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)",
853 private_layer, private_layer->waiting_buffer,
854 (layer_commit_handler->committed_buffer) ? layer_commit_handler->committed_buffer->buffer : NULL);
856 if (!private_display->commit_per_vblank) {
857 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed);
859 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
860 ret = tdm_output_commit_internal(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
861 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
863 if (tdm_debug_module & TDM_DEBUG_COMMIT)
864 TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer);
866 TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed);
868 if (private_layer->committing)
869 TDM_WRN("layer(%d) too many commit", private_layer->index);
871 private_layer->committing = 1;
873 if (_tdm_layer_commit_possible(private_layer)) {
874 /* add to layer_commit_handler_list */
875 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
876 ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
877 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
879 if (tdm_debug_module & TDM_DEBUG_COMMIT)
880 TDM_INFO("layer(%p) commit: output", private_layer);
882 /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
883 LIST_ADDTAIL(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
885 if (tdm_debug_module & TDM_DEBUG_COMMIT)
886 TDM_INFO("layer(%p) commit: pending", private_layer);
889 if (!private_output->vblank) {
890 /* tdm_vblank APIs is for server. it should be called in unlock status*/
891 _pthread_mutex_unlock(&private_display->lock);
892 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
893 _pthread_mutex_lock(&private_display->lock);
894 TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
897 if (!private_output->layer_waiting_vblank) {
898 /* tdm_vblank APIs is for server. it should be called in unlock status*/
899 _pthread_mutex_unlock(&private_display->lock);
900 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
901 _pthread_mutex_lock(&private_display->lock);
902 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
903 private_output->layer_waiting_vblank = 1;
905 if (tdm_debug_module & TDM_DEBUG_COMMIT)
906 TDM_INFO("layer(%p) commit: wait vblank", private_layer);
913 if (layer_commit_handler) {
914 private_layer->waiting_buffer = layer_commit_handler->committed_buffer;
915 LIST_DEL(&layer_commit_handler->link);
916 free(layer_commit_handler);
922 tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
926 _pthread_mutex_lock(&private_display->lock);
928 if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) {
929 if (!private_display->commit_per_vblank)
930 private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT;
932 private_display->commit_type = TDM_COMMIT_TYPE_LAYER;
935 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
936 TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe,
937 tdm_dpms_str(private_output->current_dpms_value));
938 _pthread_mutex_unlock(&private_display->lock);
939 return TDM_ERROR_DPMS_OFF;
942 /* don't call this inside of _tdm_layer_commit */
943 ret = tdm_layer_commit_pending_data(private_layer);
944 if (ret != TDM_ERROR_NONE) {
945 TDM_ERR("layer(%p) committing pending data failed", layer);
946 _pthread_mutex_unlock(&private_display->lock);
950 ret = _tdm_layer_commit(private_layer, func, user_data);
952 _pthread_mutex_unlock(&private_display->lock);
958 tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing)
962 TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER);
964 _pthread_mutex_lock(&private_display->lock);
966 *committing = private_layer->committing;
968 _pthread_mutex_unlock(&private_display->lock);
974 tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
976 tdm_private_layer *private_layer = (tdm_private_layer*)layer;
977 tdm_private_output *private_output = private_layer->private_output;
978 tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
980 TDM_RETURN_IF_FAIL(private_layer != NULL);
981 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
983 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
984 if (lm->func == func && lm->user_data == user_data) {
986 tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
987 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
993 LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
994 if (lm->func == func && lm->user_data == user_data) {
996 tdm_output_remove_commit_handler_internal(private_output, _tdm_layer_cb_output_commit, lm);
997 _tdm_layer_free_buffer(private_layer, lm->committed_buffer);
1005 tdm_layer_remove_commit_handler(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
1009 _pthread_mutex_lock(&private_display->lock);
1011 tdm_layer_remove_commit_handler_internal(layer, func, user_data);
1013 _pthread_mutex_unlock(&private_display->lock);
1018 EXTERN tbm_surface_h
1019 tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error)
1021 tbm_surface_h buffer;
1022 LAYER_FUNC_ENTRY_ERROR();
1024 _pthread_mutex_lock(&private_display->lock);
1027 *error = TDM_ERROR_NONE;
1029 if (private_layer->showing_buffer) {
1030 buffer = private_layer->showing_buffer->buffer;
1033 *error = TDM_ERROR_OPERATION_FAILED;
1034 _pthread_mutex_unlock(&private_display->lock);
1035 TDM_DBG("layer(%p) showing_buffer is null", private_layer);
1038 _pthread_mutex_unlock(&private_display->lock);
1044 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1046 TDM_RETURN_IF_FAIL(data != NULL);
1047 tdm_layer *layer = data;
1048 tdm_func_layer *func_layer;
1049 tbm_surface_h surface = NULL;
1050 tdm_private_layer_buffer *layer_buffer;
1051 LAYER_FUNC_ENTRY_VOID_RETURN();
1053 _pthread_mutex_lock(&private_display->lock);
1055 func_layer = &private_display->func_layer;
1056 if (!func_layer->layer_set_buffer) {
1057 _pthread_mutex_unlock(&private_display->lock);
1061 layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
1062 if (!layer_buffer) {
1063 _pthread_mutex_unlock(&private_display->lock);
1064 TDM_ERR("alloc failed");
1067 LIST_INITHEAD(&layer_buffer->link);
1069 if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) ||
1071 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1072 private_layer, surface);
1073 _pthread_mutex_unlock(&private_display->lock);
1078 /* we don't need to handle pending data here because the changes in this function
1079 * should be applied immediately. we can't expect calling tdm_layer_commit.
1081 ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1082 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1084 if (ret == TDM_ERROR_NONE) {
1085 if (private_layer->waiting_buffer) {
1086 TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer);
1087 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1090 private_layer->waiting_buffer = layer_buffer;
1091 private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface);
1093 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1094 TDM_INFO("layer(%p) waiting_buffer(%p)",
1095 private_layer, private_layer->waiting_buffer->buffer);
1097 if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) {
1098 ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL);
1099 if (ret != TDM_ERROR_NONE)
1100 TDM_ERR("tdm_output_commit_internal() is fail");
1101 } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) {
1102 ret = _tdm_layer_commit(private_layer, NULL, NULL);
1103 if (ret != TDM_ERROR_NONE)
1104 TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer);
1106 TDM_NEVER_GET_HERE();
1109 _tdm_layer_free_buffer(private_layer, layer_buffer);
1111 _pthread_mutex_unlock(&private_display->lock);
1115 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1117 TDM_RETURN_IF_FAIL(data != NULL);
1118 tdm_layer *layer = data;
1119 LAYER_FUNC_ENTRY_VOID_RETURN();
1120 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1122 _pthread_mutex_lock(&private_display->lock);
1124 private_layer->buffer_queue = NULL;
1126 _tdm_layer_free_all_buffers(private_layer);
1128 _pthread_mutex_unlock(&private_display->lock);
1132 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1134 tdm_func_layer *func_layer;
1137 TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1139 _pthread_mutex_lock(&private_display->lock);
1141 func_layer = &private_display->func_layer;
1143 if (private_layer->usable)
1144 TDM_INFO("layer(%p) not usable", private_layer);
1146 private_layer->usable = 0;
1148 if (!func_layer->layer_set_buffer) {
1149 _pthread_mutex_unlock(&private_display->lock);
1150 TDM_ERR("not implemented!!");
1151 return TDM_ERROR_NOT_IMPLEMENTED;
1154 if (buffer_queue == private_layer->buffer_queue) {
1155 _pthread_mutex_unlock(&private_display->lock);
1156 return TDM_ERROR_NONE;
1159 if (private_layer->waiting_buffer) {
1160 _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
1161 private_layer->waiting_buffer = NULL;
1163 if (tdm_debug_module & TDM_DEBUG_BUFFER)
1164 TDM_INFO("layer(%p) waiting_buffer(%p)",
1165 private_layer, private_layer->waiting_buffer);
1168 private_layer->buffer_queue = buffer_queue;
1169 tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1170 _tbm_layer_queue_acquirable_cb,
1172 tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1173 _tbm_layer_queue_destroy_cb,
1175 _pthread_mutex_unlock(&private_display->lock);
1181 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1183 return tdm_layer_unset_buffer(layer);
1187 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1191 TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1193 _pthread_mutex_lock(&private_display->lock);
1195 *usable = private_layer->usable;
1197 _pthread_mutex_unlock(&private_display->lock);
1203 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1205 tdm_func_layer *func_layer;
1208 _pthread_mutex_lock(&private_display->lock);
1210 func_layer = &private_display->func_layer;
1212 if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1213 TDM_ERR("layer(%p) is not video layer", private_layer);
1214 _pthread_mutex_unlock(&private_display->lock);
1215 return TDM_ERROR_INVALID_PARAMETER;
1218 if (!func_layer->layer_set_video_pos) {
1219 _pthread_mutex_unlock(&private_display->lock);
1220 TDM_ERR("not implemented!!");
1221 return TDM_ERROR_NOT_IMPLEMENTED;
1224 ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1226 _pthread_mutex_unlock(&private_display->lock);
1231 EXTERN tdm_capture *
1232 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1234 tdm_capture *capture = NULL;
1236 LAYER_FUNC_ENTRY_ERROR();
1238 _pthread_mutex_lock(&private_display->lock);
1240 capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer, error);
1242 _pthread_mutex_unlock(&private_display->lock);
1248 tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1250 tdm_func_layer *func_layer;
1253 _pthread_mutex_lock(&private_display->lock);
1255 func_layer = &private_display->func_layer;
1257 if (!func_layer->layer_get_buffer_flags) {
1258 _pthread_mutex_unlock(&private_display->lock);
1259 TDM_ERR("not implemented!!");
1260 return TDM_ERROR_NOT_IMPLEMENTED;
1263 ret = func_layer->layer_get_buffer_flags(private_layer->layer_backend, flags);
1265 _pthread_mutex_unlock(&private_display->lock);