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 <boram1288.park@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 **************************************************************************/
40 #include "tdm_private.h"
44 #define DISPLAY_FUNC_ENTRY() \
45 tdm_private_display *private_display; \
46 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
47 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); \
48 private_display = (tdm_private_display*)dpy;
50 #define DISPLAY_FUNC_ENTRY_ERROR() \
51 tdm_private_display *private_display; \
52 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
53 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
54 private_display = (tdm_private_display*)dpy;
56 #define BACKEND_FUNC_ENTRY() \
57 tdm_private_module *private_module; \
58 tdm_private_display *private_display; \
59 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
60 TDM_RETURN_VAL_IF_FAIL(module != NULL, TDM_ERROR_INVALID_PARAMETER); \
61 private_module = (tdm_private_module*)module; \
62 private_display = private_module->private_display;
66 tdm_display_enable_debug_module(const char*modules)
68 char temp[TDM_PATH_LEN];
72 snprintf(temp, TDM_PATH_LEN, "%s", modules);
76 arg = strtok_r(temp, TDM_CONFIG_DELIM, &end);
78 if (!strncmp(arg, "none", 4)) {
80 return TDM_ERROR_NONE;
82 if (!strncmp(arg, "all", 3)) {
83 tdm_debug_module = 0xFFFFFFFF;
84 return TDM_ERROR_NONE;
86 if (!strncmp(arg, "buffer", 6))
87 tdm_debug_module |= TDM_DEBUG_BUFFER;
88 else if (!strncmp(arg, "event", 5))
89 tdm_debug_module |= TDM_DEBUG_EVENT;
90 else if (!strncmp(arg, "thread", 6))
91 tdm_debug_module |= TDM_DEBUG_THREAD;
92 else if (!strncmp(arg, "mutex", 5))
93 tdm_debug_module |= TDM_DEBUG_MUTEX;
94 else if (!strncmp(arg, "vblank", 6))
95 tdm_debug_module |= TDM_DEBUG_VBLANK;
96 else if (!strncmp(arg, "commit", 6))
97 tdm_debug_module |= TDM_DEBUG_COMMIT;
99 arg = strtok_r(NULL, TDM_CONFIG_DELIM, &end);
102 TDM_INFO("module debugging... '%s'", modules);
104 return TDM_ERROR_NONE;
108 _tdm_display_enable_dump_current(tdm_private_display *private_display, char *path)
110 tdm_private_module *b = NULL;
111 tdm_private_output *o = NULL;
113 LIST_FOR_EACH_ENTRY(b, &private_display->module_list, link) {
114 LIST_FOR_EACH_ENTRY(o, &b->output_list, link) {
115 if (o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) {
116 tdm_private_hwc *private_hwc = NULL;
117 tdm_private_hwc_window *w = NULL;
119 private_hwc = o->private_hwc;
120 if (private_hwc->display_target_buffer) {
121 char str[TDM_PATH_LEN];
122 snprintf(str, TDM_PATH_LEN, "window_%d_target", private_hwc->index);
123 tdm_helper_dump_buffer_str(private_hwc->display_target_buffer, path, str);
125 LIST_FOR_EACH_ENTRY(w, &private_hwc->hwc_window_list, link) {
126 char str[TDM_PATH_LEN];
127 if (!w->display_buffer)
129 if (w->composition_type != TDM_HWC_WIN_COMPOSITION_DEVICE)
131 snprintf(str, TDM_PATH_LEN, "window_%d_%d", private_hwc->index, index++);
132 tdm_helper_dump_buffer_str(w->display_buffer, path, str);
135 tdm_private_layer *l = NULL;
136 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
137 char str[TDM_PATH_LEN];
138 if (l->usable || l->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)
140 if (!l->showing_buffer)
142 snprintf(str, TDM_PATH_LEN, "layer_%d_%d", o->index, l->index);
143 tdm_helper_dump_buffer_str(l->showing_buffer->buffer, path, str);
151 tdm_display_enable_dump(tdm_private_display *private_display, const char *dump_str, char *reply, int *len)
153 char temp[TDM_PATH_LEN] = {0,}, temp2[TDM_PATH_LEN] = {0,};
154 char *path = NULL, *path2;
158 snprintf(temp2, TDM_PATH_LEN, "%s", dump_str);
159 path2 = strtostr(temp, TDM_PATH_LEN, temp2, "@");
160 if (!path2 || path2[0] == '\0')
161 path2 = TDM_DUMP_DIR;
167 snprintf(temp, sizeof(temp), "%s", dump_str);
168 arg = strtok_r(temp, ",", &end);
169 TDM_GOTO_IF_FAIL(arg != NULL, done);
171 if (!strncmp(arg, "none", 4)) {
173 TDM_SNPRINTF(reply, len, "path: %s\n", (tdm_debug_dump_dir) ? : "unknown");
174 if (tdm_debug_dump_dir) {
175 free(tdm_debug_dump_dir);
176 tdm_debug_dump_dir = NULL;
181 path = tdm_helper_dump_make_directory(path2, reply, len);
182 TDM_GOTO_IF_FAIL(path != NULL, done);
184 if (!strncmp(arg, "current", 7)) {
185 if (!private_display) {
186 TDM_WRN("no private_display");
190 _tdm_display_enable_dump_current(private_display, path);
191 TDM_SNPRINTF(reply, len, "path: %s\n", path);
195 TDM_SNPRINTF(reply, len, "dump: %s\n", arg);
198 if (!strncmp(arg, "all", 3)) {
199 tdm_debug_dump = 0xFFFFFFFF;
201 } else if (!strncmp(arg, "layer", 5)) {
202 tdm_debug_dump |= TDM_DUMP_FLAG_LAYER;
203 } else if (!strncmp(arg, "pp", 2)) {
204 tdm_debug_dump |= TDM_DUMP_FLAG_PP;
205 } else if (!strncmp(arg, "capture", 7)) {
206 tdm_debug_dump |= TDM_DUMP_FLAG_CAPTURE;
207 } else if (!strncmp(arg, "window", 6)) {
208 tdm_debug_dump |= TDM_DUMP_FLAG_WINDOW;
212 arg = strtok_r(NULL, ",", &end);
215 if (tdm_debug_dump_dir)
216 free(tdm_debug_dump_dir);
218 tdm_debug_dump_dir = strndup(path, TDM_PATH_LEN);
220 TDM_INFO("dump... '%s'", dump_str);
226 return TDM_ERROR_NONE;
230 _tdm_display_ttrace_vblank_cb(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
231 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
233 tdm_error ret = TDM_ERROR_NONE;
235 TDM_TRACE_MARK("VSYNC");
237 ret = tdm_vblank_wait(vblank, 0, 0, 1, _tdm_display_ttrace_vblank_cb, NULL);
238 TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
242 tdm_display_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable)
244 tdm_private_display *private_display = dpy;
245 tdm_private_module *private_module = NULL;
246 tdm_private_output *private_output = NULL;
247 const tdm_output_mode *mode = NULL;
248 tdm_vblank *vblank = NULL;
249 tdm_error ret = TDM_ERROR_NONE;
252 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
253 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
254 if (private_output->ttrace_vblank)
255 tdm_vblank_destroy(private_output->ttrace_vblank);
256 private_output->ttrace_vblank = NULL;
259 return TDM_ERROR_NONE;
262 private_output = output;
263 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
265 if (private_output->ttrace_vblank)
266 return TDM_ERROR_NONE;
268 vblank = tdm_vblank_create(private_display, output, &ret);
269 TDM_RETURN_VAL_IF_FAIL(vblank != NULL, ret);
271 ret = tdm_output_get_mode(output, &mode);
272 TDM_GOTO_IF_FAIL(mode != NULL, enable_fail);
274 ret = tdm_vblank_set_fps(vblank, mode->vrefresh);
275 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, enable_fail);
277 ret = tdm_vblank_set_enable_fake(vblank, 1);
278 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, enable_fail);
280 ret = tdm_vblank_wait(vblank, 0, 0, 1, _tdm_display_ttrace_vblank_cb, NULL);
281 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, enable_fail);
283 private_output->ttrace_vblank = vblank;
285 return TDM_ERROR_NONE;
289 tdm_vblank_destroy(vblank);
295 tdm_display_enable_ttrace(tdm_private_display *private_display, const char *ttrace, int output_id, char *reply, int *len)
297 char temp[TDM_PATH_LEN];
302 tdm_output_type type;
304 snprintf(temp, TDM_PATH_LEN, "%s", ttrace);
306 tdm_ttrace_output = output_id;
307 tdm_ttrace_module = 0;
309 output = tdm_display_get_output(private_display, output_id, &ret);
311 TDM_SNPRINTF(reply, len, "can't find the output_id(%d)\n", output_id);
315 ret = tdm_output_get_output_type(output, &type);
316 if (ret != TDM_ERROR_NONE) {
317 TDM_SNPRINTF(reply, len, "can't find the type of output_id(%d)\n", output_id);
321 arg = strtok_r(temp, TDM_CONFIG_DELIM, &end);
323 if (!strncmp(arg, "none", 4))
324 tdm_ttrace_module = 0;
325 else if (!strncmp(arg, "all", 3))
326 tdm_ttrace_module = 0xFFFFFFFF;
327 else if (!strncmp(arg, "vsync", 5))
328 tdm_ttrace_module |= TDM_TTRACE_VSYNC;
329 else if (!strncmp(arg, "client_vblank", 13))
330 tdm_ttrace_module |= TDM_TTRACE_CLIENT_VBLANK;
331 else if (!strncmp(arg, "server_vblank", 13))
332 tdm_ttrace_module |= TDM_TTRACE_SERVER_VBLANK;
333 else if (!strncmp(arg, "vblank", 6))
334 tdm_ttrace_module |= TDM_TTRACE_VBLANK;
335 else if (!strncmp(arg, "layer", 5))
336 tdm_ttrace_module |= TDM_TTRACE_LAYER;
337 else if (!strncmp(arg, "pp", 2))
338 tdm_ttrace_module |= TDM_TTRACE_PP;
339 else if (!strncmp(arg, "capture", 7))
340 tdm_ttrace_module |= TDM_TTRACE_CAPTURE;
342 tdm_ttrace_module = 0;
343 tdm_display_enable_ttrace_vblank(private_display, NULL, 0);
344 tdm_server_enable_ttrace_client_vblank(private_display, NULL, 0);
345 TDM_SNPRINTF(reply, len, "unknown option: '%s'\n", arg);
346 return TDM_ERROR_NONE;
349 arg = strtok_r(NULL, TDM_CONFIG_DELIM, &end);
352 TDM_SNPRINTF(reply, len, "ttrace debugging... '%s' %x\n", ttrace, tdm_ttrace_module);
354 if (tdm_ttrace_module & TDM_TTRACE_VSYNC)
355 tdm_display_enable_ttrace_vblank(private_display, output, 1);
357 tdm_display_enable_ttrace_vblank(private_display, NULL, 0);
359 if (tdm_ttrace_module & TDM_TTRACE_CLIENT_VBLANK)
360 tdm_server_enable_ttrace_client_vblank(private_display, output, 1);
362 tdm_server_enable_ttrace_client_vblank(private_display, NULL, 0);
364 return TDM_ERROR_NONE;
368 tdm_display_enable_fps(tdm_private_display *private_display, int enable)
370 private_display->print_fps = enable;
372 TDM_INFO("print fps: %s", (enable) ? "enable" : "disable");
374 return TDM_ERROR_NONE;
379 tdm_display_call_thread_cb_output_create(tdm_private_display *private_display, tdm_output *output)
381 tdm_thread_cb_display_output_create output_create;
384 if (LIST_IS_EMPTY(&private_display->output_create_handler_list)) return TDM_ERROR_NONE;
386 memset(&output_create, 0, sizeof output_create);
387 output_create.base.type = TDM_THREAD_CB_DISPLAY_OUTPUT_CREATE;
388 output_create.base.length = sizeof output_create;
389 output_create.base.object_stamp = tdm_helper_get_time();
390 output_create.base.data = NULL;
391 output_create.base.sync = 1;
392 output_create.output = output;
394 ret = tdm_thread_cb_call(private_display, &output_create.base, 1);
395 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
397 return TDM_ERROR_NONE;
400 /* LCOV_EXCL_START */
402 tdm_display_thread_cb_output_create(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
404 tdm_thread_cb_display_output_create *output_create = (tdm_thread_cb_display_output_create*)cb_base;
405 tdm_private_output_create_handler *create_handler = user_data;
406 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
408 assert(create_handler->owner_tid == syscall(SYS_gettid));
410 _pthread_mutex_unlock(&private_display->lock);
411 create_handler->func(private_display, output_create->output, create_handler->user_data);
412 _pthread_mutex_lock(&private_display->lock);
416 tdm_display_add_output_create_handler(tdm_display *dpy,
417 tdm_output_create_handler func,
420 tdm_private_output_create_handler *create_handler = NULL;
422 DISPLAY_FUNC_ENTRY();
424 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
426 _pthread_mutex_lock(&private_display->lock);
428 LIST_FOR_EACH_ENTRY(create_handler, &private_display->output_create_handler_list, link) {
429 if (create_handler->func == func && create_handler->user_data == user_data) {
430 TDM_ERR("can't add twice");
431 _pthread_mutex_unlock(&private_display->lock);
432 return TDM_ERROR_BAD_REQUEST;
436 create_handler = calloc(1, sizeof(tdm_private_output_create_handler));
437 if (!create_handler) {
438 TDM_ERR("failed: alloc memory");
439 _pthread_mutex_unlock(&private_display->lock);
440 return TDM_ERROR_OUT_OF_MEMORY;
443 ret = tdm_thread_cb_add(private_display, TDM_THREAD_CB_DISPLAY_OUTPUT_CREATE, NULL,
444 tdm_display_thread_cb_output_create, create_handler);
445 if (ret != TDM_ERROR_NONE) {
446 TDM_ERR("tdm_thread_cb_add failed");
447 free(create_handler);
448 _pthread_mutex_unlock(&private_display->lock);
449 return TDM_ERROR_OPERATION_FAILED;
452 create_handler->private_display = private_display;
453 create_handler->func = func;
454 create_handler->user_data = user_data;
455 create_handler->owner_tid = syscall(SYS_gettid);
457 LIST_ADDTAIL(&create_handler->link, &private_display->output_create_handler_list);
459 _pthread_mutex_unlock(&private_display->lock);
465 tdm_display_remove_output_create_handler(tdm_display *dpy,
466 tdm_output_create_handler func,
469 tdm_private_display *private_display;
470 tdm_private_output_create_handler *create_handler = NULL, *hh = NULL;
472 TDM_RETURN_IF_FAIL(dpy != NULL);
473 TDM_RETURN_IF_FAIL(func != NULL);
475 private_display = (tdm_private_display*)dpy;
477 _pthread_mutex_lock(&private_display->lock);
479 LIST_FOR_EACH_ENTRY_SAFE(create_handler, hh, &private_display->output_create_handler_list, link) {
480 if (create_handler->func != func || create_handler->user_data != user_data)
483 tdm_thread_cb_remove(private_display, TDM_THREAD_CB_DISPLAY_OUTPUT_CREATE, NULL,
484 tdm_display_thread_cb_output_create, create_handler);
486 LIST_DEL(&create_handler->link);
487 free(create_handler);
489 _pthread_mutex_unlock(&private_display->lock);
494 _pthread_mutex_unlock(&private_display->lock);
499 tdm_display_get_capabilities(tdm_display *dpy,
500 tdm_display_capability *capabilities)
502 tdm_private_module *private_module = NULL;
504 DISPLAY_FUNC_ENTRY();
506 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
508 _pthread_mutex_lock(&private_display->lock);
512 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
513 *capabilities |= private_module->capabilities;
516 _pthread_mutex_unlock(&private_display->lock);
522 tdm_display_get_pp_capabilities(tdm_display *dpy,
523 tdm_pp_capability *capabilities)
525 tdm_private_module *pp_module;
527 DISPLAY_FUNC_ENTRY();
529 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
531 _pthread_mutex_lock(&private_display->lock);
533 if (!private_display->pp_module) {
534 /* LCOV_EXCL_START */
535 TDM_ERR("no pp capability");
536 _pthread_mutex_unlock(&private_display->lock);
537 return TDM_ERROR_NO_CAPABILITY;
541 pp_module = private_display->pp_module;
543 *capabilities = pp_module->caps_pp.capabilities;
545 _pthread_mutex_unlock(&private_display->lock);
551 tdm_display_get_pp_available_formats(tdm_display *dpy,
552 const tbm_format **formats, int *count)
554 tdm_private_module *pp_module;
556 DISPLAY_FUNC_ENTRY();
558 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
559 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
561 _pthread_mutex_lock(&private_display->lock);
563 if (!private_display->pp_module) {
564 /* LCOV_EXCL_START */
565 TDM_ERR("no pp capability");
566 _pthread_mutex_unlock(&private_display->lock);
567 return TDM_ERROR_NO_CAPABILITY;
571 pp_module = private_display->pp_module;
573 *formats = (const tbm_format *)pp_module->caps_pp.formats;
574 *count = pp_module->caps_pp.format_count;
576 _pthread_mutex_unlock(&private_display->lock);
582 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
583 int *max_w, int *max_h, int *preferred_align)
585 tdm_private_module *pp_module;
587 DISPLAY_FUNC_ENTRY();
589 _pthread_mutex_lock(&private_display->lock);
591 if (!private_display->pp_module) {
592 /* LCOV_EXCL_START */
593 TDM_ERR("no pp capability");
594 _pthread_mutex_unlock(&private_display->lock);
595 return TDM_ERROR_NO_CAPABILITY;
599 pp_module = private_display->pp_module;
602 *min_w = TDM_FRONT_VALUE(pp_module->caps_pp.min_w);
604 *min_h = TDM_FRONT_VALUE(pp_module->caps_pp.min_h);
606 *max_w = TDM_FRONT_VALUE(pp_module->caps_pp.max_w);
608 *max_h = TDM_FRONT_VALUE(pp_module->caps_pp.max_h);
610 *preferred_align = TDM_FRONT_VALUE(pp_module->caps_pp.preferred_align);
612 _pthread_mutex_unlock(&private_display->lock);
618 tdm_display_get_pp_preferred_align_vertical(tdm_display *dpy, int *preferred_align_vertical)
620 tdm_private_module *pp_module;
622 DISPLAY_FUNC_ENTRY();
624 _pthread_mutex_lock(&private_display->lock);
626 if (!private_display->pp_module) {
627 /* LCOV_EXCL_START */
628 TDM_ERR("no pp capability");
629 _pthread_mutex_unlock(&private_display->lock);
630 return TDM_ERROR_NO_CAPABILITY;
634 pp_module = private_display->pp_module;
636 if (preferred_align_vertical)
637 *preferred_align_vertical = TDM_FRONT_VALUE(pp_module->caps_pp.preferred_align_vertical);
639 _pthread_mutex_unlock(&private_display->lock);
645 tdm_display_get_capture_capabilities(tdm_display *dpy,
646 tdm_capture_capability *capabilities)
648 tdm_private_module *capture_module;
650 DISPLAY_FUNC_ENTRY();
652 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
654 _pthread_mutex_lock(&private_display->lock);
656 if (!private_display->capture_module) {
657 /* LCOV_EXCL_START */
658 TDM_ERR("no capture capability");
659 _pthread_mutex_unlock(&private_display->lock);
660 return TDM_ERROR_NO_CAPABILITY;
664 capture_module = private_display->capture_module;
666 *capabilities = capture_module->caps_capture.capabilities;
668 _pthread_mutex_unlock(&private_display->lock);
674 tdm_display_get_capture_available_formats(tdm_display *dpy,
675 const tbm_format **formats, int *count)
677 tdm_private_module *capture_module;
679 DISPLAY_FUNC_ENTRY();
681 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
682 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
684 _pthread_mutex_lock(&private_display->lock);
686 if (!private_display->capture_module) {
687 /* LCOV_EXCL_START */
688 TDM_ERR("no capture capability");
689 _pthread_mutex_unlock(&private_display->lock);
690 return TDM_ERROR_NO_CAPABILITY;
694 capture_module = private_display->capture_module;
696 *formats = (const tbm_format *)capture_module->caps_capture.formats;
697 *count = capture_module->caps_capture.format_count;
699 _pthread_mutex_unlock(&private_display->lock);
705 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
706 int *max_w, int *max_h, int *preferred_align)
708 tdm_private_module *capture_module;
710 DISPLAY_FUNC_ENTRY();
712 _pthread_mutex_lock(&private_display->lock);
714 if (!private_display->capture_module) {
715 /* LCOV_EXCL_START */
716 TDM_ERR("no capture capability");
717 _pthread_mutex_unlock(&private_display->lock);
718 return TDM_ERROR_NO_CAPABILITY;
722 capture_module = private_display->capture_module;
725 *min_w = TDM_FRONT_VALUE(capture_module->caps_capture.min_w);
727 *min_h = TDM_FRONT_VALUE(capture_module->caps_capture.min_h);
729 *max_w = TDM_FRONT_VALUE(capture_module->caps_capture.max_w);
731 *max_h = TDM_FRONT_VALUE(capture_module->caps_capture.max_h);
733 *preferred_align = TDM_FRONT_VALUE(capture_module->caps_capture.preferred_align);
735 _pthread_mutex_unlock(&private_display->lock);
741 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
743 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
744 TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
746 TDM_DEPRECATED(NULL);
750 return TDM_ERROR_NONE;
754 tdm_display_get_output_count(tdm_display *dpy, int *count)
756 tdm_private_module *private_module = NULL;
757 tdm_private_output *private_output = NULL;
759 DISPLAY_FUNC_ENTRY();
761 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
763 _pthread_mutex_lock(&private_display->lock);
766 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
767 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
772 _pthread_mutex_unlock(&private_display->lock);
779 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
781 tdm_private_module *private_module = NULL;
782 tdm_private_output *private_output = NULL;
784 DISPLAY_FUNC_ENTRY_ERROR();
786 _pthread_mutex_lock(&private_display->lock);
789 *error = TDM_ERROR_NONE;
791 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
792 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
793 if (private_output->index == index) {
794 _pthread_mutex_unlock(&private_display->lock);
795 return private_output;
800 _pthread_mutex_unlock(&private_display->lock);
806 tdm_display_find_output(tdm_display *dpy, const char *name, tdm_error *error)
808 tdm_private_module *private_module = NULL;
809 tdm_private_output *private_output = NULL;
810 tdm_private_output *mode_setted_output = NULL;
811 tdm_private_output *connected_output = NULL;
812 unsigned int find_primary = 0;
814 DISPLAY_FUNC_ENTRY_ERROR();
816 if (!strncasecmp(name, "primary", 7) || !strncasecmp(name, "default", 7))
819 _pthread_mutex_lock(&private_display->lock);
822 *error = TDM_ERROR_NONE;
825 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
826 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
827 if (private_output->caps.status == TDM_OUTPUT_CONN_STATUS_CONNECTED && !connected_output)
828 connected_output = private_output;
829 else if (private_output->caps.status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED && !mode_setted_output)
830 mode_setted_output = private_output;
834 if (mode_setted_output) {
835 _pthread_mutex_unlock(&private_display->lock);
836 return mode_setted_output;
839 if (connected_output) {
840 _pthread_mutex_unlock(&private_display->lock);
841 return connected_output;
844 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
845 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
846 if (private_output->index == 0) {
847 _pthread_mutex_unlock(&private_display->lock);
848 return private_output;
854 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
855 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
856 if (strncmp(private_output->caps.model, name, TDM_NAME_LEN))
858 _pthread_mutex_unlock(&private_display->lock);
859 return private_output;
863 if (private_display->virtual_module) {
864 private_module = private_display->virtual_module;
865 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
866 if (strncmp(private_output->name, name, TDM_NAME_LEN))
868 _pthread_mutex_unlock(&private_display->lock);
869 return private_output;
872 _pthread_mutex_unlock(&private_display->lock);
878 tdm_display_get_fd(tdm_display *dpy, int *fd)
880 DISPLAY_FUNC_ENTRY();
882 TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
884 _pthread_mutex_lock(&private_display->lock);
886 if (tdm_thread_is_running())
887 *fd = tdm_thread_get_fd(private_display->private_loop);
889 *fd = tdm_event_loop_get_fd(private_display);
891 _pthread_mutex_unlock(&private_display->lock);
897 tdm_display_handle_events(tdm_display *dpy)
902 DISPLAY_FUNC_ENTRY();
904 ret = tdm_display_get_fd(dpy, &fd);
905 TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
911 if (tdm_debug_module & TDM_DEBUG_EVENT)
912 TDM_INFO("fd(%d) polling in", fd);
914 while (poll(&fds, 1, -1) < 0) {
915 /* LCOV_EXCL_START */
916 if (errno == EINTR || errno == EAGAIN) /* normal case */
919 TDM_ERR("poll failed: %m");
920 return TDM_ERROR_OPERATION_FAILED;
925 if (tdm_debug_module & TDM_DEBUG_EVENT)
926 TDM_INFO("fd(%d) polling out", fd);
928 if (tdm_thread_is_running()) {
929 _pthread_mutex_lock(&private_display->lock);
930 ret = tdm_thread_handle_cb(private_display->private_loop);
931 _pthread_mutex_unlock(&private_display->lock);
933 ret = tdm_event_loop_dispatch(private_display);
940 tdm_display_flush(tdm_display *dpy)
942 tdm_private_display *private_display;
944 TDM_RETURN_IF_FAIL(dpy != NULL);
945 private_display = (tdm_private_display*)dpy;
947 if (tdm_thread_is_running())
950 tdm_event_loop_flush(private_display);
954 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
955 const char **vendor, int *major, int *minor)
957 tdm_private_module *private_module = NULL;
958 tdm_backend_module *module_data = NULL;
960 DISPLAY_FUNC_ENTRY();
962 TDM_DEPRECATED("Use tdm_module_get_info");
964 _pthread_mutex_lock(&private_display->lock);
966 /* use first backend */
967 LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
968 module_data = private_module->module_data;
972 assert(module_data != NULL);
975 *name = module_data->name;
977 *vendor = module_data->vendor;
979 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
981 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
983 _pthread_mutex_unlock(&private_display->lock);
989 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
993 DISPLAY_FUNC_ENTRY_ERROR();
995 _pthread_mutex_lock(&private_display->lock);
997 pp = (tdm_pp *)tdm_pp_create_internal(private_display->pp_module, error);
999 _pthread_mutex_unlock(&private_display->lock);
1005 tdm_module_get_info(tdm_module *module, const char **name,
1006 const char **vendor, int *major, int *minor)
1008 tdm_backend_module *module_data;
1010 BACKEND_FUNC_ENTRY();
1012 _pthread_mutex_lock(&private_display->lock);
1014 module_data = private_module->module_data;
1017 *name = module_data->name;
1019 *vendor = module_data->vendor;
1021 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
1023 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
1025 _pthread_mutex_unlock(&private_display->lock);
1031 tdm_module_check_abi(tdm_private_module *private_module, int abimaj, int abimin)
1033 tdm_backend_module *module = private_module->module_data;
1035 if (!private_module->use_hal_tdm) {
1036 if (TDM_BACKEND_GET_ABI_MAJOR(module->abi_version) > abimaj)
1039 if (TDM_BACKEND_GET_ABI_MAJOR(module->abi_version) < abimaj)
1042 if (TDM_BACKEND_GET_ABI_MINOR(module->abi_version) < abimin)
1049 /* LCOV_EXCL_START */
1050 INTERN tdm_voutput *
1051 tdm_display_voutput_create(tdm_display *dpy, const char *name, tdm_error *error)
1053 tdm_private_module *private_module = NULL;
1054 tdm_private_module *current_module = NULL;
1055 tdm_private_voutput *private_voutput = NULL;
1056 tdm_private_output *private_output = NULL;
1057 tdm_func_display *func_display = NULL;
1058 tdm_func_voutput *func_voutput = NULL;
1059 tdm_voutput *voutput_backend = NULL;
1060 tdm_output *output_backend = NULL;
1061 int output_find = 0;
1062 tdm_private_display *private_display;
1063 tdm_error ret = TDM_ERROR_NONE;
1065 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL);
1066 private_display = (tdm_private_display*)dpy;
1067 private_module = private_display->virtual_module;
1068 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_module != NULL, TDM_ERROR_BAD_MODULE, NULL);
1070 _pthread_mutex_lock(&private_display->lock);
1072 if (error) *error = TDM_ERROR_NONE;
1074 private_voutput = calloc(1, sizeof(tdm_private_voutput));
1075 if (!private_voutput) {
1076 if (error) *error = TDM_ERROR_OUT_OF_MEMORY;
1077 _pthread_mutex_unlock(&private_display->lock);
1081 current_module = private_display->current_module;
1082 private_display->current_module = private_module;
1084 if (private_module->use_hal_tdm) {
1085 voutput_backend = (tdm_voutput *)hal_tdm_display_voutput_create(private_module->htdm_dpy, name, (hal_tdm_error *)&ret);
1087 func_display = &private_module->func_display;
1088 func_voutput = &private_module->func_voutput;
1089 voutput_backend = func_display->display_voutput_create(private_module->bdata, name, &ret);
1091 if (voutput_backend == NULL || ret != TDM_ERROR_NONE) {
1092 TDM_ERR("display_voutput_create fail");
1093 if (error) *error = ret;
1094 goto voutput_create_fail;
1096 private_voutput->voutput_backend = voutput_backend;
1097 private_voutput->private_display = private_display;
1098 private_voutput->private_module = private_module;
1099 LIST_INITHEAD(&private_voutput->voutput_commit_handler_list);
1101 if (private_module->use_hal_tdm)
1102 output_backend = (tdm_output *)hal_tdm_voutput_get_output((hal_tdm_voutput *)voutput_backend, (hal_tdm_error *)&ret);
1104 output_backend = func_voutput->voutput_get_output(voutput_backend, &ret);
1105 if (output_backend == NULL || ret != TDM_ERROR_NONE) {
1106 TDM_ERR("voutput_get_output fail");
1107 if (error) *error = ret;
1108 goto output_get_fail;
1111 if (private_module->use_hal_tdm) {
1112 if (private_module->use_default_type_bo == 1)
1113 hal_tdm_voutput_set_target_buffer_queue_flag((hal_tdm_voutput *)voutput_backend, TBM_BO_DEFAULT);
1115 hal_tdm_voutput_set_target_buffer_queue_flag((hal_tdm_voutput *)voutput_backend, TBM_BO_SCANOUT);
1117 if (func_voutput->voutput_set_target_buffer_queue_flag) {
1118 if (private_module->use_default_type_bo == 1)
1119 func_voutput->voutput_set_target_buffer_queue_flag(voutput_backend, TBM_BO_DEFAULT);
1121 func_voutput->voutput_set_target_buffer_queue_flag(voutput_backend, TBM_BO_SCANOUT);
1125 ret = tdm_display_update_output(private_display->current_module, output_backend);
1126 if (ret != TDM_ERROR_NONE) {
1127 TDM_ERR("tdm_display_update_output fail");
1128 if (error) *error = ret;
1129 goto update_output_fail;
1132 LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
1133 if (private_output->output_backend == output_backend) {
1139 if (output_find != 1) {
1140 private_output = NULL;
1141 free(private_voutput);
1142 if (private_module->use_hal_tdm) {
1143 hal_tdm_voutput_destroy((hal_tdm_voutput *)voutput_backend);
1145 if (func_voutput->voutput_destroy)
1146 func_voutput->voutput_destroy(voutput_backend);
1148 TDM_ERR("no destroy function");
1150 private_voutput = NULL;
1152 strncpy(private_voutput->name, name, TDM_NAME_LEN - 1);
1153 private_voutput->name[TDM_NAME_LEN - 1] = '\0';
1154 strncpy(private_output->name, name, TDM_NAME_LEN - 1);
1155 private_output->name[TDM_NAME_LEN - 1] = '\0';
1157 private_voutput->private_output = private_output;
1158 private_output->private_voutput = private_voutput;
1160 /* do not use vblank */
1161 tdm_output_choose_commit_per_vblank_mode(private_output, 0);
1163 LIST_ADDTAIL(&private_voutput->link, &private_module->voutput_list);
1166 private_display->current_module = current_module;
1168 _pthread_mutex_unlock(&private_display->lock);
1170 return private_voutput;
1174 if (private_module->use_hal_tdm) {
1175 hal_tdm_voutput_destroy((hal_tdm_voutput *)voutput_backend);
1177 if (func_voutput->voutput_destroy)
1178 func_voutput->voutput_destroy(voutput_backend);
1180 TDM_ERR("no destroy function");
1182 voutput_create_fail:
1183 free(private_voutput);
1184 private_display->current_module = current_module;
1185 _pthread_mutex_unlock(&private_display->lock);
1189 /* LCOV_EXCL_STOP */