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"
46 #define DISPLAY_FUNC_ENTRY() \
47 tdm_private_display *private_display; \
48 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
49 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
50 private_display = (tdm_private_display*)dpy;
52 #define DISPLAY_FUNC_ENTRY_ERROR() \
53 tdm_private_display *private_display; \
54 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
55 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
56 private_display = (tdm_private_display*)dpy;
58 #define OUTPUT_FUNC_ENTRY() \
59 tdm_private_display *private_display; \
60 tdm_private_output *private_output; \
61 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
62 TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \
63 private_output = (tdm_private_output*)output; \
64 private_display = private_output->private_display
66 #define OUTPUT_FUNC_ENTRY_ERROR() \
67 tdm_private_display *private_display; \
68 tdm_private_output *private_output; \
69 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
70 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
71 private_output = (tdm_private_output*)output; \
72 private_display = private_output->private_display
74 #define LAYER_FUNC_ENTRY() \
75 tdm_private_display *private_display; \
76 tdm_private_output *private_output; \
77 tdm_private_layer *private_layer; \
78 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
79 TDM_RETURN_VAL_IF_FAIL(layer != NULL, TDM_ERROR_INVALID_PARAMETER); \
80 private_layer = (tdm_private_layer*)layer; \
81 private_output = private_layer->private_output; \
82 private_display = private_output->private_display
84 #define LAYER_FUNC_ENTRY_ERROR() \
85 tdm_private_display *private_display; \
86 tdm_private_output *private_output; \
87 tdm_private_layer *private_layer; \
88 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
89 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(layer != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
90 private_layer = (tdm_private_layer*)layer; \
91 private_output = private_layer->private_output; \
92 private_display = private_output->private_display
94 #define LAYER_FUNC_ENTRY_VOID_RETURN() \
95 tdm_private_display *private_display; \
96 tdm_private_output *private_output; \
97 tdm_private_layer *private_layer; \
98 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
99 TDM_RETURN_IF_FAIL(layer != NULL); \
100 private_layer = (tdm_private_layer*)layer; \
101 private_output = private_layer->private_output; \
102 private_display = private_output->private_display
104 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
111 #define type_name_fn(res) \
112 const char * res##_str(int type) { \
114 for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
115 if (res##_names[i].type == type) \
116 return res##_names[i].name; \
118 return "(invalid)"; \
121 struct type_name dpms_names[] = {
122 { TDM_OUTPUT_DPMS_ON, "on" },
123 { TDM_OUTPUT_DPMS_STANDBY, "standby" },
124 { TDM_OUTPUT_DPMS_SUSPEND, "suspend" },
125 { TDM_OUTPUT_DPMS_OFF, "off" },
128 static type_name_fn(dpms)
130 struct type_name status_names[] = {
131 { TDM_OUTPUT_CONN_STATUS_DISCONNECTED, "disconnected" },
132 { TDM_OUTPUT_CONN_STATUS_CONNECTED, "connected" },
133 { TDM_OUTPUT_CONN_STATUS_MODE_SETTED, "mode_setted" },
136 static type_name_fn(status)
139 tdm_display_get_capabilities(tdm_display *dpy,
140 tdm_display_capability *capabilities)
142 DISPLAY_FUNC_ENTRY();
144 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
146 _pthread_mutex_lock(&private_display->lock);
148 *capabilities = private_display->capabilities;
150 _pthread_mutex_unlock(&private_display->lock);
156 tdm_display_get_pp_capabilities(tdm_display *dpy,
157 tdm_pp_capability *capabilities)
159 DISPLAY_FUNC_ENTRY();
161 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
163 _pthread_mutex_lock(&private_display->lock);
165 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
166 TDM_ERR("no pp capability");
167 _pthread_mutex_unlock(&private_display->lock);
168 return TDM_ERROR_NO_CAPABILITY;
171 *capabilities = private_display->caps_pp.capabilities;
173 _pthread_mutex_unlock(&private_display->lock);
179 tdm_display_get_pp_available_formats(tdm_display *dpy,
180 const tbm_format **formats, int *count)
182 DISPLAY_FUNC_ENTRY();
184 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
185 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
187 _pthread_mutex_lock(&private_display->lock);
189 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
190 TDM_ERR("no pp capability");
191 _pthread_mutex_unlock(&private_display->lock);
192 return TDM_ERROR_NO_CAPABILITY;
195 *formats = (const tbm_format *)private_display->caps_pp.formats;
196 *count = private_display->caps_pp.format_count;
198 _pthread_mutex_unlock(&private_display->lock);
204 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
205 int *max_w, int *max_h, int *preferred_align)
207 DISPLAY_FUNC_ENTRY();
209 _pthread_mutex_lock(&private_display->lock);
211 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
212 TDM_ERR("no pp capability");
213 _pthread_mutex_unlock(&private_display->lock);
214 return TDM_ERROR_NO_CAPABILITY;
218 *min_w = private_display->caps_pp.min_w;
220 *min_h = private_display->caps_pp.min_h;
222 *max_w = private_display->caps_pp.max_w;
224 *max_h = private_display->caps_pp.max_h;
226 *preferred_align = private_display->caps_pp.preferred_align;
228 _pthread_mutex_unlock(&private_display->lock);
234 tdm_display_get_capture_capabilities(tdm_display *dpy,
235 tdm_capture_capability *capabilities)
237 DISPLAY_FUNC_ENTRY();
239 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
241 _pthread_mutex_lock(&private_display->lock);
243 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
244 TDM_ERR("no capture capability");
245 _pthread_mutex_unlock(&private_display->lock);
246 return TDM_ERROR_NO_CAPABILITY;
249 *capabilities = private_display->caps_capture.capabilities;
251 _pthread_mutex_unlock(&private_display->lock);
257 tdm_display_get_catpure_available_formats(tdm_display *dpy,
258 const tbm_format **formats, int *count)
260 DISPLAY_FUNC_ENTRY();
262 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
263 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
265 _pthread_mutex_lock(&private_display->lock);
267 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
268 TDM_ERR("no capture capability");
269 _pthread_mutex_unlock(&private_display->lock);
270 return TDM_ERROR_NO_CAPABILITY;
273 *formats = (const tbm_format *)private_display->caps_capture.formats;
274 *count = private_display->caps_capture.format_count;
276 _pthread_mutex_unlock(&private_display->lock);
282 tdm_display_get_output_count(tdm_display *dpy, int *count)
284 tdm_private_output *private_output = NULL;
286 DISPLAY_FUNC_ENTRY();
288 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
290 _pthread_mutex_lock(&private_display->lock);
293 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
297 _pthread_mutex_unlock(&private_display->lock);
298 return TDM_ERROR_NONE;
301 _pthread_mutex_unlock(&private_display->lock);
308 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
310 tdm_private_output *private_output = NULL;
313 DISPLAY_FUNC_ENTRY_ERROR();
315 _pthread_mutex_lock(&private_display->lock);
318 *error = TDM_ERROR_NONE;
321 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
323 _pthread_mutex_unlock(&private_display->lock);
324 return private_output;
329 _pthread_mutex_unlock(&private_display->lock);
335 tdm_display_get_fd(tdm_display *dpy, int *fd)
337 DISPLAY_FUNC_ENTRY();
339 TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
341 _pthread_mutex_lock(&private_display->lock);
343 *fd = tdm_event_get_fd(private_display);
345 _pthread_mutex_unlock(&private_display->lock);
351 tdm_display_handle_events(tdm_display *dpy)
353 DISPLAY_FUNC_ENTRY();
355 _pthread_mutex_lock(&private_display->lock);
357 ret = tdm_event_dispatch(private_display);
359 _pthread_mutex_unlock(&private_display->lock);
365 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
369 DISPLAY_FUNC_ENTRY_ERROR();
371 _pthread_mutex_lock(&private_display->lock);
373 pp = (tdm_pp *)tdm_pp_create_internal(private_display, error);
375 _pthread_mutex_unlock(&private_display->lock);
381 tdm_output_get_model_info(tdm_output *output, const char **maker,
382 const char **model, const char **name)
386 _pthread_mutex_lock(&private_display->lock);
389 *maker = private_output->caps.maker;
391 *model = private_output->caps.model;
393 *name = private_output->caps.name;
395 _pthread_mutex_unlock(&private_display->lock);
401 tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status)
405 TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER);
407 _pthread_mutex_lock(&private_display->lock);
409 *status = private_output->caps.status;
411 _pthread_mutex_unlock(&private_display->lock);
417 tdm_output_add_change_handler(tdm_output *output,
418 tdm_output_change_handler func,
421 tdm_private_change_handler *change_handler;
424 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
426 pthread_mutex_lock(&private_display->lock);
428 if (!private_output->regist_change_cb) {
429 _pthread_mutex_unlock(&private_display->lock);
430 TDM_DBG("failed: not implemented!!");
431 return TDM_ERROR_NOT_IMPLEMENTED;
434 change_handler = calloc(1, sizeof(tdm_private_change_handler));
435 if (!change_handler) {
436 TDM_ERR("failed: alloc memory");
437 _pthread_mutex_unlock(&private_display->lock);
438 return TDM_ERROR_OUT_OF_MEMORY;
441 LIST_ADD(&change_handler->link, &private_output->change_handler_list);
442 change_handler->private_output = private_output;
443 change_handler->func = func;
444 change_handler->user_data = user_data;
446 _pthread_mutex_unlock(&private_display->lock);
452 tdm_output_remove_change_handler(tdm_output *output,
453 tdm_output_change_handler func,
456 tdm_private_display *private_display;
457 tdm_private_output *private_output;
458 tdm_private_change_handler *h = NULL, *hh = NULL;
460 TDM_RETURN_IF_FAIL(output != NULL);
461 TDM_RETURN_IF_FAIL(func != NULL);
463 private_output = (tdm_private_output*)output;
464 private_display = private_output->private_display;
466 _pthread_mutex_lock(&private_display->lock);
468 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
469 if (h->func != func || h->user_data != user_data)
475 _pthread_mutex_unlock(&private_display->lock);
480 _pthread_mutex_unlock(&private_display->lock);
484 tdm_output_get_output_type(tdm_output *output, tdm_output_type *type)
488 TDM_RETURN_VAL_IF_FAIL(type != NULL, TDM_ERROR_INVALID_PARAMETER);
490 _pthread_mutex_lock(&private_display->lock);
492 *type = private_output->caps.type;
494 _pthread_mutex_unlock(&private_display->lock);
500 tdm_output_get_layer_count(tdm_output *output, int *count)
502 tdm_private_layer *private_layer = NULL;
506 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
508 _pthread_mutex_lock(&private_display->lock);
511 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
514 _pthread_mutex_unlock(&private_display->lock);
515 return TDM_ERROR_NONE;
518 _pthread_mutex_unlock(&private_display->lock);
525 tdm_output_get_layer(tdm_output *output, int index, tdm_error *error)
527 tdm_private_layer *private_layer = NULL;
530 OUTPUT_FUNC_ENTRY_ERROR();
532 _pthread_mutex_lock(&private_display->lock);
535 *error = TDM_ERROR_NONE;
537 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
539 _pthread_mutex_unlock(&private_display->lock);
540 return private_layer;
545 _pthread_mutex_unlock(&private_display->lock);
551 tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props,
556 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
557 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
559 _pthread_mutex_lock(&private_display->lock);
561 *props = (const tdm_prop *)private_output->caps.props;
562 *count = private_output->caps.prop_count;
564 _pthread_mutex_unlock(&private_display->lock);
570 tdm_output_get_available_modes(tdm_output *output,
571 const tdm_output_mode **modes, int *count)
575 TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
576 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
578 _pthread_mutex_lock(&private_display->lock);
580 *modes = (const tdm_output_mode *)private_output->caps.modes;
581 *count = private_output->caps.mode_count;
583 _pthread_mutex_unlock(&private_display->lock);
589 tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h,
590 int *max_w, int *max_h, int *preferred_align)
594 _pthread_mutex_lock(&private_display->lock);
597 *min_w = private_output->caps.min_w;
599 *min_h = private_output->caps.min_h;
601 *max_w = private_output->caps.max_w;
603 *max_h = private_output->caps.max_h;
605 *preferred_align = private_output->caps.preferred_align;
607 _pthread_mutex_unlock(&private_display->lock);
613 tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth,
614 unsigned int *mmHeight)
618 _pthread_mutex_lock(&private_display->lock);
621 *mmWidth = private_output->caps.mmWidth;
623 *mmHeight = private_output->caps.mmHeight;
625 _pthread_mutex_unlock(&private_display->lock);
631 tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel)
634 TDM_RETURN_VAL_IF_FAIL(subpixel != NULL, TDM_ERROR_INVALID_PARAMETER);
636 _pthread_mutex_lock(&private_display->lock);
638 *subpixel = private_output->caps.subpixel;
640 _pthread_mutex_unlock(&private_display->lock);
646 tdm_output_get_pipe(tdm_output *output, unsigned int *pipe)
649 TDM_RETURN_VAL_IF_FAIL(pipe != NULL, TDM_ERROR_INVALID_PARAMETER);
651 _pthread_mutex_lock(&private_display->lock);
653 *pipe = private_output->pipe;
655 _pthread_mutex_unlock(&private_display->lock);
662 tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
664 tdm_func_output *func_output;
667 _pthread_mutex_lock(&private_display->lock);
669 func_output = &private_display->func_output;
671 if (!func_output->output_set_property) {
672 _pthread_mutex_unlock(&private_display->lock);
673 TDM_DBG("failed: not implemented!!");
674 return TDM_ERROR_NOT_IMPLEMENTED;
677 ret = func_output->output_set_property(private_output->output_backend, id,
680 _pthread_mutex_unlock(&private_display->lock);
686 tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
688 tdm_func_output *func_output;
691 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
693 _pthread_mutex_lock(&private_display->lock);
695 func_output = &private_display->func_output;
697 if (!func_output->output_get_property) {
698 _pthread_mutex_unlock(&private_display->lock);
699 TDM_DBG("failed: not implemented!!");
700 return TDM_ERROR_NOT_IMPLEMENTED;
703 ret = func_output->output_get_property(private_output->output_backend, id,
706 _pthread_mutex_unlock(&private_display->lock);
712 _tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
713 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
715 tdm_private_vblank_handler *vblank_handler = user_data;
716 tdm_private_display *private_display;
718 TDM_RETURN_IF_FAIL(vblank_handler);
720 private_display = vblank_handler->private_output->private_display;
722 if (vblank_handler->func) {
723 _pthread_mutex_unlock(&private_display->lock);
724 vblank_handler->func(vblank_handler->private_output, sequence,
725 tv_sec, tv_usec, vblank_handler->user_data);
726 _pthread_mutex_lock(&private_display->lock);
729 LIST_DEL(&vblank_handler->link);
730 free(vblank_handler);
734 _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
735 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
737 tdm_private_commit_handler *commit_handler = user_data;
738 tdm_private_display *private_display;
739 tdm_private_output *private_output;
740 tdm_private_layer *private_layer = NULL;
742 TDM_RETURN_IF_FAIL(commit_handler);
744 private_output = commit_handler->private_output;
745 private_display = private_output->private_display;
747 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
748 if (!private_layer->waiting_buffer)
751 if (private_layer->showing_buffer) {
752 _pthread_mutex_unlock(&private_display->lock);
753 tdm_buffer_unref_backend(private_layer->showing_buffer);
754 _pthread_mutex_lock(&private_display->lock);
756 if (private_layer->buffer_queue) {
757 _pthread_mutex_unlock(&private_display->lock);
758 tbm_surface_queue_release(private_layer->buffer_queue,
759 private_layer->showing_buffer);
760 _pthread_mutex_lock(&private_display->lock);
764 private_layer->showing_buffer = private_layer->waiting_buffer;
765 private_layer->waiting_buffer = NULL;
767 if (tdm_debug_buffer)
768 TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)",
769 private_layer, private_layer->waiting_buffer,
770 private_layer->showing_buffer);
773 if (commit_handler->func) {
774 _pthread_mutex_unlock(&private_display->lock);
775 commit_handler->func(private_output, sequence,
776 tv_sec, tv_usec, commit_handler->user_data);
777 _pthread_mutex_lock(&private_display->lock);
780 LIST_DEL(&commit_handler->link);
781 free(commit_handler);
785 tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
786 tdm_output_vblank_handler func, void *user_data)
788 tdm_func_output *func_output;
789 tdm_private_vblank_handler *vblank_handler;
792 _pthread_mutex_lock(&private_display->lock);
794 func_output = &private_display->func_output;
796 if (!func_output->output_wait_vblank) {
797 _pthread_mutex_unlock(&private_display->lock);
798 TDM_DBG("failed: not implemented!!");
799 return TDM_ERROR_NOT_IMPLEMENTED;
802 vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler));
803 if (!vblank_handler) {
804 TDM_ERR("failed: alloc memory");
805 _pthread_mutex_unlock(&private_display->lock);
806 return TDM_ERROR_OUT_OF_MEMORY;
809 LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
810 vblank_handler->private_output = private_output;
811 vblank_handler->func = func;
812 vblank_handler->user_data = user_data;
814 ret = func_output->output_wait_vblank(private_output->output_backend, interval,
815 sync, vblank_handler);
816 if (ret != TDM_ERROR_NONE) {
817 _pthread_mutex_unlock(&private_display->lock);
821 if (!private_output->regist_vblank_cb) {
822 private_output->regist_vblank_cb = 1;
823 ret = func_output->output_set_vblank_handler(private_output->output_backend,
824 _tdm_output_cb_vblank);
827 _pthread_mutex_unlock(&private_display->lock);
833 _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
836 tdm_func_output *func_output;
837 tdm_private_commit_handler *commit_handler;
840 func_output = &private_display->func_output;
842 if (!func_output->output_commit) {
843 TDM_DBG("failed: not implemented!!");
844 return TDM_ERROR_NOT_IMPLEMENTED;
847 commit_handler = calloc(1, sizeof(tdm_private_commit_handler));
848 if (!commit_handler) {
849 TDM_ERR("failed: alloc memory");
850 return TDM_ERROR_OUT_OF_MEMORY;
853 LIST_ADD(&commit_handler->link, &private_output->commit_handler_list);
854 commit_handler->private_output = private_output;
855 commit_handler->func = func;
856 commit_handler->user_data = user_data;
858 ret = func_output->output_commit(private_output->output_backend, sync,
860 TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
862 if (!private_output->regist_commit_cb) {
863 private_output->regist_commit_cb = 1;
864 ret = func_output->output_set_commit_handler(private_output->output_backend,
865 _tdm_output_cb_commit);
872 tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
877 _pthread_mutex_lock(&private_display->lock);
879 ret = _tdm_output_commit(output, sync, func, user_data);
881 _pthread_mutex_unlock(&private_display->lock);
887 tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
889 tdm_func_output *func_output;
892 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
894 _pthread_mutex_lock(&private_display->lock);
896 func_output = &private_display->func_output;
898 if (!func_output->output_set_mode) {
899 _pthread_mutex_unlock(&private_display->lock);
900 TDM_DBG("failed: not implemented!!");
901 return TDM_ERROR_NOT_IMPLEMENTED;
904 ret = func_output->output_set_mode(private_output->output_backend, mode);
906 _pthread_mutex_unlock(&private_display->lock);
912 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
914 tdm_func_output *func_output;
917 TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER);
919 _pthread_mutex_lock(&private_display->lock);
921 func_output = &private_display->func_output;
923 if (!func_output->output_get_mode) {
924 _pthread_mutex_unlock(&private_display->lock);
925 TDM_DBG("failed: not implemented!!");
926 return TDM_ERROR_NOT_IMPLEMENTED;
929 ret = func_output->output_get_mode(private_output->output_backend, mode);
931 _pthread_mutex_unlock(&private_display->lock);
937 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
939 tdm_func_output *func_output;
942 if (dpms_value < TDM_OUTPUT_DPMS_ON)
943 dpms_value = TDM_OUTPUT_DPMS_ON;
944 else if (dpms_value > TDM_OUTPUT_DPMS_OFF)
945 dpms_value = TDM_OUTPUT_DPMS_OFF;
947 _pthread_mutex_lock(&private_display->lock);
949 func_output = &private_display->func_output;
951 if (!func_output->output_set_dpms) {
952 _pthread_mutex_unlock(&private_display->lock);
953 TDM_DBG("failed: not implemented!!");
954 return TDM_ERROR_NOT_IMPLEMENTED;
957 ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
959 _pthread_mutex_unlock(&private_display->lock);
965 tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
967 tdm_func_output *func_output;
970 TDM_RETURN_VAL_IF_FAIL(dpms_value != NULL, TDM_ERROR_INVALID_PARAMETER);
972 _pthread_mutex_lock(&private_display->lock);
974 func_output = &private_display->func_output;
976 if (!func_output->output_get_dpms) {
977 _pthread_mutex_unlock(&private_display->lock);
978 TDM_DBG("failed: not implemented!!");
979 return TDM_ERROR_NOT_IMPLEMENTED;
982 ret = func_output->output_get_dpms(private_output->output_backend, dpms_value);
984 _pthread_mutex_unlock(&private_display->lock);
990 tdm_output_create_capture(tdm_output *output, tdm_error *error)
992 tdm_capture *capture = NULL;
994 OUTPUT_FUNC_ENTRY_ERROR();
996 _pthread_mutex_lock(&private_display->lock);
998 capture = (tdm_capture *)tdm_capture_create_output_internal(private_output,
1001 _pthread_mutex_unlock(&private_display->lock);
1007 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
1008 tdm_output_change_type type,
1011 tdm_private_change_handler *change_handler;
1012 tdm_private_display *private_display;
1014 TDM_RETURN_IF_FAIL(private_output);
1016 private_display = private_output->private_display;
1018 if (type & TDM_OUTPUT_CHANGE_CONNECTION)
1019 TDM_INFO("output(%d) changed: %s",
1020 private_output->pipe, status_str(value.u32));
1021 if (type & TDM_OUTPUT_CHANGE_DPMS)
1022 TDM_INFO("output(%d) changed: dpms %s",
1023 private_output->pipe, dpms_str(value.u32));
1025 _pthread_mutex_unlock(&private_display->lock);
1027 LIST_FOR_EACH_ENTRY(change_handler, &private_output->change_handler_list, link) {
1028 change_handler->func(private_output, type,
1029 value, change_handler->user_data);
1032 _pthread_mutex_lock(&private_display->lock);
1036 tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
1040 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
1042 _pthread_mutex_lock(&private_display->lock);
1044 *capabilities = private_layer->caps.capabilities;
1046 _pthread_mutex_unlock(&private_display->lock);
1052 tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats,
1057 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
1058 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1060 _pthread_mutex_lock(&private_display->lock);
1062 *formats = (const tbm_format *)private_layer->caps.formats;
1063 *count = private_layer->caps.format_count;
1065 _pthread_mutex_unlock(&private_display->lock);
1071 tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props,
1076 TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
1077 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
1079 _pthread_mutex_lock(&private_display->lock);
1081 *props = (const tdm_prop *)private_layer->caps.props;
1082 *count = private_layer->caps.prop_count;
1084 _pthread_mutex_unlock(&private_display->lock);
1090 tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos)
1094 TDM_RETURN_VAL_IF_FAIL(zpos != NULL, TDM_ERROR_INVALID_PARAMETER);
1096 _pthread_mutex_lock(&private_display->lock);
1098 *zpos = private_layer->caps.zpos;
1100 _pthread_mutex_unlock(&private_display->lock);
1106 tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1108 tdm_func_layer *func_layer;
1111 _pthread_mutex_lock(&private_display->lock);
1113 func_layer = &private_display->func_layer;
1115 if (!func_layer->layer_set_property) {
1116 _pthread_mutex_unlock(&private_display->lock);
1117 TDM_DBG("failed: not implemented!!");
1118 return TDM_ERROR_NOT_IMPLEMENTED;
1121 ret = func_layer->layer_set_property(private_layer->layer_backend, id, value);
1123 _pthread_mutex_unlock(&private_display->lock);
1129 tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1131 tdm_func_layer *func_layer;
1134 TDM_RETURN_VAL_IF_FAIL(value != NULL, TDM_ERROR_INVALID_PARAMETER);
1136 _pthread_mutex_lock(&private_display->lock);
1138 func_layer = &private_display->func_layer;
1140 if (!func_layer->layer_get_property) {
1141 _pthread_mutex_unlock(&private_display->lock);
1142 TDM_DBG("failed: not implemented!!");
1143 return TDM_ERROR_NOT_IMPLEMENTED;
1146 ret = func_layer->layer_get_property(private_layer->layer_backend, id, value);
1148 _pthread_mutex_unlock(&private_display->lock);
1154 tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1156 tdm_func_layer *func_layer;
1159 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1161 _pthread_mutex_lock(&private_display->lock);
1163 func_layer = &private_display->func_layer;
1165 private_layer->usable = 0;
1167 if (!func_layer->layer_set_info) {
1168 _pthread_mutex_unlock(&private_display->lock);
1169 TDM_DBG("failed: not implemented!!");
1170 return TDM_ERROR_NOT_IMPLEMENTED;
1173 TDM_INFO("layer(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%d,%d %dx%d) trans(%d)",
1174 private_layer, info->src_config.size.h, info->src_config.size.v,
1175 info->src_config.pos.x, info->src_config.pos.y,
1176 info->src_config.pos.w, info->src_config.pos.h,
1177 FOURCC_STR(info->src_config.format),
1178 info->dst_pos.x, info->dst_pos.y,
1179 info->dst_pos.w, info->dst_pos.h,
1182 ret = func_layer->layer_set_info(private_layer->layer_backend, info);
1183 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1185 _pthread_mutex_unlock(&private_display->lock);
1191 tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1193 tdm_func_layer *func_layer;
1196 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
1198 _pthread_mutex_lock(&private_display->lock);
1200 func_layer = &private_display->func_layer;
1202 if (!func_layer->layer_get_info) {
1203 _pthread_mutex_unlock(&private_display->lock);
1204 TDM_DBG("failed: not implemented!!");
1205 return TDM_ERROR_NOT_IMPLEMENTED;
1208 ret = func_layer->layer_get_info(private_layer->layer_backend, info);
1210 _pthread_mutex_unlock(&private_display->lock);
1216 tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1218 tdm_func_layer *func_layer;
1222 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
1224 _pthread_mutex_lock(&private_display->lock);
1226 func_layer = &private_display->func_layer;
1228 private_layer->usable = 0;
1230 if (!func_layer->layer_set_buffer) {
1231 _pthread_mutex_unlock(&private_display->lock);
1232 TDM_DBG("failed: not implemented!!");
1233 return TDM_ERROR_NOT_IMPLEMENTED;
1236 ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
1237 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1239 if (ret == TDM_ERROR_NONE) {
1240 /* FIXME: should save to pending_buffer first. And after committing
1241 * successfully, need to move to waiting_buffer.
1243 if (private_layer->waiting_buffer) {
1244 _pthread_mutex_unlock(&private_display->lock);
1245 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1246 _pthread_mutex_lock(&private_display->lock);
1249 private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer);
1250 if (tdm_debug_buffer)
1251 TDM_INFO("layer(%p) waiting_buffer(%p)",
1252 private_layer, private_layer->waiting_buffer);
1255 _pthread_mutex_unlock(&private_display->lock);
1261 tdm_layer_unset_buffer(tdm_layer *layer)
1263 tdm_func_layer *func_layer;
1266 _pthread_mutex_lock(&private_display->lock);
1268 func_layer = &private_display->func_layer;
1270 if (private_layer->waiting_buffer) {
1271 _pthread_mutex_unlock(&private_display->lock);
1272 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1273 _pthread_mutex_lock(&private_display->lock);
1274 private_layer->waiting_buffer = NULL;
1276 if (tdm_debug_buffer)
1277 TDM_INFO("layer(%p) waiting_buffer(%p)",
1278 private_layer, private_layer->waiting_buffer);
1281 if (private_layer->showing_buffer) {
1282 _pthread_mutex_unlock(&private_display->lock);
1283 tdm_buffer_unref_backend(private_layer->showing_buffer);
1284 _pthread_mutex_lock(&private_display->lock);
1285 private_layer->showing_buffer = NULL;
1287 if (tdm_debug_buffer)
1288 TDM_INFO("layer(%p) showing_buffer(%p)",
1289 private_layer, private_layer->showing_buffer);
1292 private_layer->usable = 1;
1294 if (!func_layer->layer_unset_buffer) {
1295 _pthread_mutex_unlock(&private_display->lock);
1296 TDM_DBG("failed: not implemented!!");
1297 return TDM_ERROR_NOT_IMPLEMENTED;
1300 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1301 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1303 _pthread_mutex_unlock(&private_display->lock);
1309 _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1311 TDM_RETURN_IF_FAIL(data != NULL);
1312 tdm_layer *layer = data;
1313 tdm_func_layer *func_layer;
1314 tbm_surface_h surface = NULL;
1315 LAYER_FUNC_ENTRY_VOID_RETURN();
1317 _pthread_mutex_lock(&private_display->lock);
1319 func_layer = &private_display->func_layer;
1320 if (!func_layer->layer_set_buffer) {
1321 _pthread_mutex_unlock(&private_display->lock);
1325 if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(
1326 private_layer->buffer_queue, &surface) ||
1328 TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p",
1329 private_layer, surface);
1330 _pthread_mutex_unlock(&private_display->lock);
1334 ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
1335 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
1337 if (ret == TDM_ERROR_NONE) {
1338 if (private_layer->waiting_buffer) {
1339 _pthread_mutex_unlock(&private_display->lock);
1340 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1341 tbm_surface_queue_release(private_layer->buffer_queue,
1342 private_layer->waiting_buffer);
1343 _pthread_mutex_lock(&private_display->lock);
1346 private_layer->waiting_buffer = tdm_buffer_ref_backend(surface);
1348 if (tdm_debug_buffer)
1349 TDM_INFO("layer(%p) waiting_buffer(%p)",
1350 private_layer, private_layer->waiting_buffer);
1352 ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
1353 if (ret != TDM_ERROR_NONE)
1354 TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer);
1357 _pthread_mutex_unlock(&private_display->lock);
1361 _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data)
1363 TDM_RETURN_IF_FAIL(data != NULL);
1364 tdm_layer *layer = data;
1365 LAYER_FUNC_ENTRY_VOID_RETURN();
1366 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
1368 _pthread_mutex_lock(&private_display->lock);
1370 if (private_layer->waiting_buffer) {
1371 _pthread_mutex_unlock(&private_display->lock);
1372 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1373 tbm_surface_queue_release(private_layer->buffer_queue,
1374 private_layer->waiting_buffer);
1375 _pthread_mutex_lock(&private_display->lock);
1378 private_layer->buffer_queue = NULL;
1380 _pthread_mutex_unlock(&private_display->lock);
1384 tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue)
1386 tdm_func_layer *func_layer;
1389 TDM_RETURN_VAL_IF_FAIL(buffer_queue != NULL, TDM_ERROR_INVALID_PARAMETER);
1391 _pthread_mutex_lock(&private_display->lock);
1393 func_layer = &private_display->func_layer;
1395 private_layer->usable = 0;
1397 if (!func_layer->layer_set_buffer) {
1398 _pthread_mutex_unlock(&private_display->lock);
1399 TDM_DBG("failed: not implemented!!");
1400 return TDM_ERROR_NOT_IMPLEMENTED;
1403 if (buffer_queue == private_layer->buffer_queue) {
1404 _pthread_mutex_unlock(&private_display->lock);
1405 return TDM_ERROR_NONE;
1408 if (private_layer->waiting_buffer) {
1409 _pthread_mutex_unlock(&private_display->lock);
1410 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1411 tbm_surface_queue_release(private_layer->buffer_queue,
1412 private_layer->waiting_buffer);
1413 private_layer->waiting_buffer = NULL;
1414 _pthread_mutex_lock(&private_display->lock);
1416 if (tdm_debug_buffer)
1417 TDM_INFO("layer(%p) waiting_buffer(%p)",
1418 private_layer, private_layer->waiting_buffer);
1421 private_layer->buffer_queue = buffer_queue;
1422 tbm_surface_queue_add_acquirable_cb(private_layer->buffer_queue,
1423 _tbm_layer_queue_acquirable_cb,
1425 tbm_surface_queue_add_destroy_cb(private_layer->buffer_queue,
1426 _tbm_layer_queue_destroy_cb,
1428 _pthread_mutex_unlock(&private_display->lock);
1434 tdm_layer_unset_buffer_queue(tdm_layer *layer)
1436 tdm_func_layer *func_layer;
1439 _pthread_mutex_lock(&private_display->lock);
1441 func_layer = &private_display->func_layer;
1443 if (private_layer->waiting_buffer) {
1444 _pthread_mutex_unlock(&private_display->lock);
1445 tdm_buffer_unref_backend(private_layer->waiting_buffer);
1446 tbm_surface_queue_release(private_layer->buffer_queue,
1447 private_layer->waiting_buffer);
1448 private_layer->waiting_buffer = NULL;
1449 _pthread_mutex_lock(&private_display->lock);
1451 if (tdm_debug_buffer)
1452 TDM_INFO("layer(%p) waiting_buffer(%p)",
1453 private_layer, private_layer->waiting_buffer);
1456 if (private_layer->showing_buffer) {
1457 _pthread_mutex_unlock(&private_display->lock);
1458 tdm_buffer_unref_backend(private_layer->showing_buffer);
1459 tbm_surface_queue_release(private_layer->buffer_queue,
1460 private_layer->showing_buffer);
1461 _pthread_mutex_lock(&private_display->lock);
1462 private_layer->showing_buffer = NULL;
1464 if (tdm_debug_buffer)
1465 TDM_INFO("layer(%p) showing_buffer(%p)",
1466 private_layer, private_layer->showing_buffer);
1469 tbm_surface_queue_remove_acquirable_cb(private_layer->buffer_queue, _tbm_layer_queue_acquirable_cb, layer);
1470 tbm_surface_queue_remove_destroy_cb(private_layer->buffer_queue, _tbm_layer_queue_destroy_cb, layer);
1471 private_layer->buffer_queue = NULL;
1472 private_layer->usable = 1;
1474 if (!func_layer->layer_unset_buffer) {
1475 _pthread_mutex_unlock(&private_display->lock);
1476 TDM_DBG("failed: not implemented!!");
1477 return TDM_ERROR_NOT_IMPLEMENTED;
1480 ret = func_layer->layer_unset_buffer(private_layer->layer_backend);
1482 _pthread_mutex_unlock(&private_display->lock);
1488 tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable)
1492 TDM_RETURN_VAL_IF_FAIL(usable != NULL, TDM_ERROR_INVALID_PARAMETER);
1494 _pthread_mutex_lock(&private_display->lock);
1496 *usable = private_layer->usable;
1498 _pthread_mutex_unlock(&private_display->lock);
1504 tdm_layer_set_video_pos(tdm_layer *layer, int zpos)
1506 tdm_func_layer *func_layer;
1509 _pthread_mutex_lock(&private_display->lock);
1511 func_layer = &private_display->func_layer;
1513 if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) {
1514 TDM_ERR("layer(%p) is not video layer", private_layer);
1515 _pthread_mutex_unlock(&private_display->lock);
1516 return TDM_ERROR_INVALID_PARAMETER;
1519 if (!func_layer->layer_set_video_pos) {
1520 _pthread_mutex_unlock(&private_display->lock);
1521 TDM_DBG("failed: not implemented!!");
1522 return TDM_ERROR_NOT_IMPLEMENTED;
1525 ret = func_layer->layer_set_video_pos(private_layer->layer_backend, zpos);
1527 _pthread_mutex_unlock(&private_display->lock);
1532 EXTERN tdm_capture *
1533 tdm_layer_create_capture(tdm_layer *layer, tdm_error *error)
1535 tdm_capture *capture = NULL;
1537 LAYER_FUNC_ENTRY_ERROR();
1539 _pthread_mutex_lock(&private_display->lock);
1541 capture = (tdm_capture *)tdm_capture_create_layer_internal(private_layer,
1544 _pthread_mutex_unlock(&private_display->lock);