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 **************************************************************************/
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 TDM_RETURN_VAL_IF_FAIL(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER); \
49 private_display = (tdm_private_display*)dpy;
51 #define DISPLAY_FUNC_ENTRY_ERROR() \
52 tdm_private_display *private_display; \
53 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
54 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
55 TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER, NULL); \
56 private_display = (tdm_private_display*)dpy;
58 #define BACKEND_FUNC_ENTRY() \
59 tdm_private_backend *private_backend; \
60 tdm_private_display *private_display; \
61 tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
62 TDM_RETURN_VAL_IF_FAIL(backend != NULL, TDM_ERROR_INVALID_PARAMETER); \
63 private_backend = (tdm_private_backend*)backend; \
64 private_display = private_backend->private_display;
67 tdm_display_get_capabilities(tdm_display *dpy,
68 tdm_display_capability *capabilities)
70 tdm_private_backend *private_backend = NULL;
74 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
76 _pthread_mutex_lock(&private_display->lock);
80 LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) {
81 *capabilities |= private_backend->capabilities;
84 _pthread_mutex_unlock(&private_display->lock);
90 tdm_display_get_pp_capabilities(tdm_display *dpy,
91 tdm_pp_capability *capabilities)
93 tdm_private_backend *pp_backend;
97 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
99 _pthread_mutex_lock(&private_display->lock);
101 if (!private_display->pp_backend) {
102 /* LCOV_EXCL_START */
103 TDM_ERR("no pp capability");
104 _pthread_mutex_unlock(&private_display->lock);
105 return TDM_ERROR_NO_CAPABILITY;
109 pp_backend = private_display->pp_backend;
111 *capabilities = pp_backend->caps_pp.capabilities;
113 _pthread_mutex_unlock(&private_display->lock);
119 tdm_display_get_pp_available_formats(tdm_display *dpy,
120 const tbm_format **formats, int *count)
122 tdm_private_backend *pp_backend;
124 DISPLAY_FUNC_ENTRY();
126 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
127 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
129 _pthread_mutex_lock(&private_display->lock);
131 if (!private_display->pp_backend) {
132 /* LCOV_EXCL_START */
133 TDM_ERR("no pp capability");
134 _pthread_mutex_unlock(&private_display->lock);
135 return TDM_ERROR_NO_CAPABILITY;
139 pp_backend = private_display->pp_backend;
141 *formats = (const tbm_format *)pp_backend->caps_pp.formats;
142 *count = pp_backend->caps_pp.format_count;
144 _pthread_mutex_unlock(&private_display->lock);
150 tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h,
151 int *max_w, int *max_h, int *preferred_align)
153 tdm_private_backend *pp_backend;
155 DISPLAY_FUNC_ENTRY();
157 _pthread_mutex_lock(&private_display->lock);
159 if (!private_display->pp_backend) {
160 /* LCOV_EXCL_START */
161 TDM_ERR("no pp capability");
162 _pthread_mutex_unlock(&private_display->lock);
163 return TDM_ERROR_NO_CAPABILITY;
167 pp_backend = private_display->pp_backend;
170 *min_w = TDM_FRONT_VALUE(pp_backend->caps_pp.min_w);
172 *min_h = TDM_FRONT_VALUE(pp_backend->caps_pp.min_h);
174 *max_w = TDM_FRONT_VALUE(pp_backend->caps_pp.max_w);
176 *max_h = TDM_FRONT_VALUE(pp_backend->caps_pp.max_h);
178 *preferred_align = TDM_FRONT_VALUE(pp_backend->caps_pp.preferred_align);
180 _pthread_mutex_unlock(&private_display->lock);
186 tdm_display_get_capture_capabilities(tdm_display *dpy,
187 tdm_capture_capability *capabilities)
189 tdm_private_backend *capture_backend;
191 DISPLAY_FUNC_ENTRY();
193 TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
195 _pthread_mutex_lock(&private_display->lock);
197 if (!private_display->capture_backend) {
198 /* LCOV_EXCL_START */
199 TDM_ERR("no capture capability");
200 _pthread_mutex_unlock(&private_display->lock);
201 return TDM_ERROR_NO_CAPABILITY;
205 capture_backend = private_display->capture_backend;
207 *capabilities = capture_backend->caps_capture.capabilities;
209 _pthread_mutex_unlock(&private_display->lock);
215 tdm_display_get_capture_available_formats(tdm_display *dpy,
216 const tbm_format **formats, int *count)
218 tdm_private_backend *capture_backend;
220 DISPLAY_FUNC_ENTRY();
222 TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
223 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
225 _pthread_mutex_lock(&private_display->lock);
227 if (!private_display->capture_backend) {
228 /* LCOV_EXCL_START */
229 TDM_ERR("no capture capability");
230 _pthread_mutex_unlock(&private_display->lock);
231 return TDM_ERROR_NO_CAPABILITY;
235 capture_backend = private_display->capture_backend;
237 *formats = (const tbm_format *)capture_backend->caps_capture.formats;
238 *count = capture_backend->caps_capture.format_count;
240 _pthread_mutex_unlock(&private_display->lock);
246 tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h,
247 int *max_w, int *max_h, int *preferred_align)
249 tdm_private_backend *capture_backend;
251 DISPLAY_FUNC_ENTRY();
253 _pthread_mutex_lock(&private_display->lock);
255 if (!private_display->capture_backend) {
256 /* LCOV_EXCL_START */
257 TDM_ERR("no capture capability");
258 _pthread_mutex_unlock(&private_display->lock);
259 return TDM_ERROR_NO_CAPABILITY;
263 capture_backend = private_display->capture_backend;
266 *min_w = TDM_FRONT_VALUE(capture_backend->caps_capture.min_w);
268 *min_h = TDM_FRONT_VALUE(capture_backend->caps_capture.min_h);
270 *max_w = TDM_FRONT_VALUE(capture_backend->caps_capture.max_w);
272 *max_h = TDM_FRONT_VALUE(capture_backend->caps_capture.max_h);
274 *preferred_align = TDM_FRONT_VALUE(capture_backend->caps_capture.preferred_align);
276 _pthread_mutex_unlock(&private_display->lock);
282 tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count)
284 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
285 TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER);
287 TDM_DEPRECATED(NULL);
291 return TDM_ERROR_NONE;
295 tdm_display_get_output_count(tdm_display *dpy, int *count)
297 tdm_private_backend *private_backend = NULL;
298 tdm_private_output *private_output = NULL;
300 DISPLAY_FUNC_ENTRY();
302 TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
304 _pthread_mutex_lock(&private_display->lock);
307 LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) {
308 LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) {
313 _pthread_mutex_unlock(&private_display->lock);
320 tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
322 tdm_private_backend *private_backend = NULL;
323 tdm_private_output *private_output = NULL;
325 DISPLAY_FUNC_ENTRY_ERROR();
327 _pthread_mutex_lock(&private_display->lock);
330 *error = TDM_ERROR_NONE;
332 LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) {
333 LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) {
334 if (private_output->index == index) {
335 _pthread_mutex_unlock(&private_display->lock);
336 return private_output;
341 _pthread_mutex_unlock(&private_display->lock);
347 tdm_display_get_fd(tdm_display *dpy, int *fd)
349 DISPLAY_FUNC_ENTRY();
351 TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
353 _pthread_mutex_lock(&private_display->lock);
355 if (tdm_thread_is_running())
356 *fd = tdm_thread_get_fd(private_display->private_loop);
358 *fd = tdm_event_loop_get_fd(private_display);
360 _pthread_mutex_unlock(&private_display->lock);
366 tdm_display_handle_events(tdm_display *dpy)
371 DISPLAY_FUNC_ENTRY();
373 ret = tdm_display_get_fd(dpy, &fd);
374 TDM_RETURN_VAL_IF_FAIL(fd >= 0, ret);
380 if (tdm_debug_module & TDM_DEBUG_EVENT)
381 TDM_INFO("fd(%d) polling in", fd);
383 while (poll(&fds, 1, -1) < 0) {
384 /* LCOV_EXCL_START */
385 if (errno == EINTR || errno == EAGAIN) /* normal case */
388 TDM_ERR("poll failed: %m");
389 return TDM_ERROR_OPERATION_FAILED;
394 if (tdm_debug_module & TDM_DEBUG_EVENT)
395 TDM_INFO("fd(%d) polling out", fd);
397 if (tdm_thread_is_running()) {
398 _pthread_mutex_lock(&private_display->lock);
399 ret = tdm_thread_handle_cb(private_display->private_loop);
400 _pthread_mutex_unlock(&private_display->lock);
402 ret = tdm_event_loop_dispatch(private_display);
409 tdm_display_flush(tdm_display *dpy)
411 tdm_private_display *private_display;
413 TDM_RETURN_IF_FAIL(dpy != NULL);
414 private_display = (tdm_private_display*)dpy;
416 if (tdm_thread_is_running())
419 tdm_event_loop_flush(private_display);
423 tdm_display_get_backend_info(tdm_display *dpy, const char **name,
424 const char **vendor, int *major, int *minor)
426 tdm_private_backend *private_backend;
427 tdm_backend_module *module_data = NULL;
429 DISPLAY_FUNC_ENTRY();
431 TDM_DEPRECATED("Use tdm_backend_get_info");
433 _pthread_mutex_lock(&private_display->lock);
435 /* use first backend */
436 LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) {
437 module_data = private_backend->module_data;
441 assert(module_data != NULL);
444 *name = module_data->name;
446 *vendor = module_data->vendor;
448 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
450 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
452 _pthread_mutex_unlock(&private_display->lock);
458 tdm_backend_get_info(tdm_backend *backend, const char **name,
459 const char **vendor, int *major, int *minor)
461 tdm_backend_module *module_data;
463 BACKEND_FUNC_ENTRY();
465 _pthread_mutex_lock(&private_display->lock);
467 module_data = private_backend->module_data;
470 *name = module_data->name;
472 *vendor = module_data->vendor;
474 *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version);
476 *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version);
478 _pthread_mutex_unlock(&private_display->lock);
484 tdm_display_create_pp(tdm_display *dpy, tdm_error *error)
488 DISPLAY_FUNC_ENTRY_ERROR();
490 _pthread_mutex_lock(&private_display->lock);
492 pp = (tdm_pp *)tdm_pp_create_internal(private_display->pp_backend, error);
494 _pthread_mutex_unlock(&private_display->lock);