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"
45 static tdm_private_layer *
46 _tdm_display_find_private_layer(tdm_private_output *private_output,
47 tdm_layer *layer_backend)
49 tdm_private_layer *private_layer = NULL;
51 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
52 if (private_layer->layer_backend == layer_backend)
59 static tdm_private_output *
60 _tdm_display_find_private_output(tdm_private_display *private_display,
61 tdm_output *output_backend)
63 tdm_private_output *private_output = NULL;
65 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
66 if (private_output->output_backend == output_backend)
67 return private_output;
73 INTERN tdm_private_output *
74 tdm_display_find_output_stamp(tdm_private_display *private_display,
77 tdm_private_output *private_output = NULL;
79 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
80 if (private_output->stamp == stamp)
81 return private_output;
88 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
90 free(caps_pp->formats);
91 memset(caps_pp, 0, sizeof(tdm_caps_pp));
95 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
97 free(caps_capture->formats);
98 memset(caps_capture, 0, sizeof(tdm_caps_capture));
102 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
104 free(caps_layer->formats);
105 free(caps_layer->props);
106 memset(caps_layer, 0, sizeof(tdm_caps_layer));
110 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
112 free(caps_output->modes);
113 free(caps_output->props);
114 memset(caps_output, 0, sizeof(tdm_caps_output));
118 _tdm_display_destroy_private_layer(tdm_private_layer *private_layer)
120 tdm_private_capture *c = NULL, *cc = NULL;
122 LIST_DEL(&private_layer->link);
124 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link)
125 tdm_capture_destroy_internal(c);
127 _tdm_display_destroy_caps_layer(&private_layer->caps);
133 _tdm_display_destroy_private_output(tdm_private_output *private_output)
135 tdm_private_layer *l = NULL, *ll = NULL;
136 tdm_private_capture *c = NULL, *cc = NULL;
137 tdm_private_vblank_handler *v = NULL, *vv = NULL;
138 tdm_private_commit_handler *m = NULL, *mm = NULL;
139 tdm_private_change_handler *h = NULL, *hh = NULL;
141 LIST_DEL(&private_output->link);
143 free(private_output->layers_ptr);
145 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
150 LIST_FOR_EACH_ENTRY_SAFE(m, mm, &private_output->commit_handler_list, link) {
155 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
160 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
161 tdm_capture_destroy_internal(c);
163 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
164 _tdm_display_destroy_private_layer(l);
166 _tdm_display_destroy_caps_output(&private_output->caps);
168 private_output->stamp = 0;
169 free(private_output);
173 _tdm_display_destroy_private_display(tdm_private_display *private_display)
175 tdm_private_output *o = NULL, *oo = NULL;
176 tdm_private_pp *p = NULL, *pp = NULL;
178 free(private_display->outputs_ptr);
180 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
181 tdm_pp_destroy_internal(p);
183 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
184 _tdm_display_destroy_private_output(o);
186 _tdm_display_destroy_caps_pp(&private_display->caps_pp);
187 _tdm_display_destroy_caps_capture(&private_display->caps_capture);
189 private_display->capabilities = 0;
190 private_display->caps_display.max_layer_count = -1;
194 _tdm_display_update_caps_pp(tdm_private_display *private_display,
197 tdm_func_display *func_display = &private_display->func_display;
199 int bufsize = sizeof(buf);
201 int *len_buf = &bufsize;
205 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
206 return TDM_ERROR_NONE;
208 if (!func_display->display_get_pp_capability) {
209 TDM_ERR("no display_get_pp_capability()");
210 return TDM_ERROR_BAD_MODULE;
213 ret = func_display->display_get_pp_capability(private_display->bdata, caps);
214 if (ret != TDM_ERROR_NONE) {
215 TDM_ERR("display_get_pp_capability() failed");
216 return TDM_ERROR_BAD_MODULE;
219 TDM_DBG("pp capabilities: %x", caps->capabilities);
221 for (i = 0; i < caps->format_count; i++)
222 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
223 TDM_DBG("pp formats: %s", buf);
224 TDM_DBG("pp min : %dx%d", caps->min_w, caps->min_h);
225 TDM_DBG("pp max : %dx%d", caps->max_w, caps->max_h);
226 TDM_DBG("pp align: %d", caps->preferred_align);
228 return TDM_ERROR_NONE;
232 _tdm_display_update_caps_capture(tdm_private_display *private_display,
233 tdm_caps_capture *caps)
235 tdm_func_display *func_display = &private_display->func_display;
237 int bufsize = sizeof(buf);
239 int *len_buf = &bufsize;
243 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
244 return TDM_ERROR_NONE;
246 if (!func_display->display_get_capture_capability) {
247 TDM_ERR("no display_get_capture_capability()");
248 return TDM_ERROR_BAD_MODULE;
251 ret = func_display->display_get_capture_capability(private_display->bdata,
253 if (ret != TDM_ERROR_NONE) {
254 TDM_ERR("display_get_capture_capability() failed");
255 return TDM_ERROR_BAD_MODULE;
259 for (i = 0; i < caps->format_count; i++)
260 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
261 TDM_DBG("capture formats: %s", buf);
263 return TDM_ERROR_NONE;
267 _tdm_display_update_caps_layer(tdm_private_display *private_display,
268 tdm_layer *layer_backend, tdm_caps_layer *caps)
270 tdm_func_layer *func_layer = &private_display->func_layer;
272 int bufsize = sizeof(buf);
274 int *len_buf = &bufsize;
278 if (!func_layer->layer_get_capability) {
279 TDM_ERR("no layer_get_capability()");
280 return TDM_ERROR_BAD_MODULE;
283 ret = func_layer->layer_get_capability(layer_backend, caps);
284 if (ret != TDM_ERROR_NONE) {
285 TDM_ERR("layer_get_capability() failed");
286 return TDM_ERROR_BAD_MODULE;
289 TDM_DBG("layer capabilities: %x", caps->capabilities);
290 TDM_DBG("layer zpos : %d", caps->zpos);
292 for (i = 0; i < caps->format_count; i++)
293 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
294 TDM_DBG("layer formats: %s", buf);
295 for (i = 0; i < caps->prop_count; i++)
296 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
298 return TDM_ERROR_NONE;
302 _tdm_display_update_caps_output(tdm_private_display *private_display,
303 tdm_output *output_backend, tdm_caps_output *caps)
305 tdm_func_output *func_output = &private_display->func_output;
309 if (!func_output->output_get_capability) {
310 TDM_ERR("no output_get_capability()");
311 return TDM_ERROR_BAD_MODULE;
314 ret = func_output->output_get_capability(output_backend, caps);
315 if (ret != TDM_ERROR_NONE) {
316 TDM_ERR("output_get_capability() failed");
317 return TDM_ERROR_BAD_MODULE;
320 TDM_DBG("output maker: %s", caps->maker);
321 TDM_DBG("output model: %s", caps->model);
322 TDM_DBG("output name: %s", caps->name);
323 TDM_DBG("output status: %d", caps->status);
324 TDM_DBG("output type : %d", caps->type);
325 for (i = 0; i < caps->prop_count; i++)
326 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
327 for (i = 0; i < caps->mode_count; i++) {
328 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
329 caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
330 caps->modes[i].flags, caps->modes[i].type);
331 TDM_DBG("\t\t %d, %d, %d, %d, %d",
332 caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
333 caps->modes[i].htotal, caps->modes[i].hskew);
334 TDM_DBG("\t\t %d, %d, %d, %d, %d",
335 caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
336 caps->modes[i].vtotal, caps->modes[i].vscan);
338 TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h);
339 TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h);
340 TDM_DBG("output align: %d", caps->preferred_align);
342 return TDM_ERROR_NONE;
346 _tdm_display_update_layer(tdm_private_display *private_display,
347 tdm_private_output *private_output,
348 tdm_layer *layer_backend)
350 tdm_private_layer *private_layer;
353 private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
354 if (!private_layer) {
355 private_layer = calloc(1, sizeof(tdm_private_layer));
356 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
358 LIST_ADD(&private_layer->link, &private_output->layer_list);
359 private_layer->private_display = private_display;
360 private_layer->private_output = private_output;
361 private_layer->layer_backend = layer_backend;
363 LIST_INITHEAD(&private_layer->capture_list);
365 private_layer->usable = 1;
367 _tdm_display_destroy_caps_layer(&private_layer->caps);
369 ret = _tdm_display_update_caps_layer(private_display, layer_backend,
370 &private_layer->caps);
371 if (ret != TDM_ERROR_NONE)
374 return TDM_ERROR_NONE;
376 _tdm_display_destroy_private_layer(private_layer);
381 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
384 tdm_private_display *private_display;
385 tdm_private_output *private_output = user_data;
388 TDM_RETURN_IF_FAIL(private_output);
390 private_display = private_output->private_display;
392 if (!tdm_thread_in_display_thread(private_display)) {
393 tdm_thread_cb_output_status output_status;
396 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
397 output_status.base.length = sizeof output_status;
398 output_status.output_stamp = private_output->stamp;
399 output_status.status = status;
400 output_status.user_data = user_data;
402 ret = tdm_thread_send_cb(private_display, &output_status.base);
403 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
409 tdm_output_call_change_handler_internal(private_output,
410 TDM_OUTPUT_CHANGE_CONNECTION,
415 _tdm_display_update_output(tdm_private_display *private_display,
416 tdm_output *output_backend, int pipe)
418 tdm_func_output *func_output = &private_display->func_output;
419 tdm_private_output *private_output = NULL;
420 tdm_layer **layers = NULL;
421 int layer_count = 0, i;
424 private_output = _tdm_display_find_private_output(private_display,
426 if (!private_output) {
427 private_output = calloc(1, sizeof(tdm_private_output));
428 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
430 private_output->stamp = tdm_helper_get_time_in_millis();
431 while (tdm_display_find_output_stamp(private_display, private_output->stamp))
432 private_output->stamp++;
434 LIST_ADD(&private_output->link, &private_display->output_list);
436 private_output->private_display = private_display;
437 private_output->output_backend = output_backend;
438 private_output->pipe = pipe;
440 LIST_INITHEAD(&private_output->layer_list);
441 LIST_INITHEAD(&private_output->capture_list);
442 LIST_INITHEAD(&private_output->vblank_handler_list);
443 LIST_INITHEAD(&private_output->commit_handler_list);
444 LIST_INITHEAD(&private_output->change_handler_list);
446 if (func_output->output_set_status_handler) {
447 private_output->regist_change_cb = 1;
448 ret = func_output->output_set_status_handler(output_backend,
449 tdm_output_cb_status,
451 if (ret != TDM_ERROR_NONE)
455 _tdm_display_destroy_caps_output(&private_output->caps);
457 ret = _tdm_display_update_caps_output(private_display, output_backend,
458 &private_output->caps);
459 if (ret != TDM_ERROR_NONE)
462 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
463 if (ret != TDM_ERROR_NONE)
466 for (i = 0; i < layer_count; i++) {
467 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
468 if (ret != TDM_ERROR_NONE)
474 return TDM_ERROR_NONE;
476 _tdm_display_destroy_private_output(private_output);
482 _tdm_display_update_internal(tdm_private_display *private_display,
485 tdm_func_display *func_display = &private_display->func_display;
486 tdm_output **outputs = NULL;
487 int output_count = 0, i;
490 LIST_INITHEAD(&private_display->output_list);
491 LIST_INITHEAD(&private_display->pp_list);
492 LIST_INITHEAD(&private_display->capture_list);
495 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
496 if (ret != TDM_ERROR_NONE)
499 ret = _tdm_display_update_caps_capture(private_display,
500 &private_display->caps_capture);
501 if (ret != TDM_ERROR_NONE)
505 outputs = func_display->display_get_outputs(private_display->bdata,
506 &output_count, &ret);
507 if (ret != TDM_ERROR_NONE)
510 for (i = 0; i < output_count; i++) {
511 ret = _tdm_display_update_output(private_display, outputs[i], i);
512 if (ret != TDM_ERROR_NONE)
518 return TDM_ERROR_NONE;
521 _tdm_display_destroy_private_display(private_display);
527 tdm_display_update(tdm_display *dpy)
529 tdm_private_display *private_display;
532 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
534 private_display = dpy;
535 _pthread_mutex_lock(&private_display->lock);
537 ret = _tdm_display_update_internal(private_display, 1);
539 _pthread_mutex_unlock(&private_display->lock);
544 #define SUFFIX_MODULE ".so"
545 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
548 int tdm_debug_buffer;
549 int tdm_debug_thread;
552 static tdm_private_display *g_private_display;
553 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
556 _tdm_display_check_module(tdm_backend_module *module)
563 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
564 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
566 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
568 name = module->name ? module->name : "unknown";
569 vendor = module->vendor ? module->vendor : "unknown";
570 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
571 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
573 TDM_INFO("TDM module name: %s", name);
574 TDM_INFO("'%s' vendor: %s", name, vendor);
575 TDM_INFO("'%s' version: %d.%d", name, major, minor);
577 if (major != abimaj) {
578 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
579 return TDM_ERROR_BAD_MODULE;
582 if (minor > abimin) {
583 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
584 return TDM_ERROR_BAD_MODULE;
588 TDM_ERR("'%s' doesn't have init function", name);
589 return TDM_ERROR_BAD_MODULE;
592 if (!module->deinit) {
593 TDM_ERR("'%s' doesn't have deinit function", name);
594 return TDM_ERROR_BAD_MODULE;
597 return TDM_ERROR_NONE;
601 _tdm_display_check_backend_functions(tdm_private_display *private_display)
603 tdm_func_display *func_display = &private_display->func_display;
604 tdm_func_output *func_output = &private_display->func_output;
605 tdm_func_layer *func_layer = &private_display->func_layer;
608 /* below functions should be implemented in backend side */
610 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
611 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
612 TDM_ERROR_BAD_MODULE);
613 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
614 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
615 TDM_ERROR_BAD_MODULE);
616 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
617 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
619 ret = func_display->display_get_capabilitiy(private_display->bdata,
620 &private_display->caps_display);
621 if (ret != TDM_ERROR_NONE) {
622 TDM_ERR("display_get_capabilitiy() failed");
623 return TDM_ERROR_BAD_MODULE;
626 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
627 tdm_func_pp *func_pp = &private_display->func_pp;
628 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
629 TDM_ERROR_BAD_MODULE);
630 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
631 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
632 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
633 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
636 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
637 tdm_func_capture *func_capture = &private_display->func_capture;
638 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
639 TDM_ERROR_BAD_MODULE);
640 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
641 TDM_ERROR_BAD_MODULE);
642 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
643 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
644 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
645 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
646 TDM_ERROR_BAD_MODULE);
649 return TDM_ERROR_NONE;
653 _tdm_display_load_module_with_file(tdm_private_display *private_display,
656 char path[PATH_MAX] = {0,};
657 tdm_backend_module *module_data;
661 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
663 TDM_TRACE_BEGIN(Load_Backend);
665 module = dlopen(path, RTLD_LAZY);
667 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
669 return TDM_ERROR_BAD_MODULE;
672 module_data = dlsym(module, "tdm_backend_module_data");
674 TDM_ERR("'%s' doesn't have data object", file);
675 ret = TDM_ERROR_BAD_MODULE;
680 private_display->module_data = module_data;
681 private_display->module = module;
683 /* check if version, init() and deinit() are valid or not */
684 ret = _tdm_display_check_module(module_data);
685 if (ret != TDM_ERROR_NONE)
690 /* We don't care if backend_data is NULL or not. It's up to backend. */
691 TDM_TRACE_BEGIN(Init_Backend);
692 private_display->bdata = module_data->init((tdm_display *)private_display,
695 if (ret != TDM_ERROR_NONE) {
696 TDM_ERR("'%s' init failed", file);
700 ret = _tdm_display_check_backend_functions(private_display);
701 if (ret != TDM_ERROR_NONE) {
702 module_data->deinit(private_display->bdata);
703 private_display->bdata = NULL;
707 TDM_INFO("Success to load module(%s)", file);
709 return TDM_ERROR_NONE;
712 private_display->module_data = NULL;
713 private_display->module = NULL;
718 _tdm_display_load_module(tdm_private_display *private_display)
720 const char *module_name;
721 struct dirent **namelist;
725 module_name = getenv("TDM_MODULE");
727 module_name = DEFAULT_MODULE;
729 /* load bufmgr priv from default lib */
730 ret = _tdm_display_load_module_with_file(private_display, module_name);
731 if (ret == TDM_ERROR_NONE)
732 return TDM_ERROR_NONE;
734 /* load bufmgr priv from configured path */
735 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
737 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
738 return TDM_ERROR_BAD_MODULE;
741 ret = TDM_ERROR_BAD_MODULE;
743 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
744 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
754 _tdm_display_unload_module(tdm_private_display *private_display)
756 if (private_display->module_data)
757 private_display->module_data->deinit(private_display->bdata);
758 if (private_display->module)
759 dlclose(private_display->module);
761 private_display->bdata = NULL;
762 private_display->module_data = NULL;
763 private_display->module = NULL;
767 tdm_display_init(tdm_error *error)
769 tdm_private_display *private_display = NULL;
773 _pthread_mutex_lock(&gLock);
775 if (g_private_display) {
776 g_private_display->init_count++;
777 _pthread_mutex_unlock(&gLock);
779 *error = TDM_ERROR_NONE;
780 return g_private_display;
783 debug = getenv("TDM_DEBUG");
784 if (debug && (strstr(debug, "1")))
787 debug = getenv("TDM_DEBUG_BUFFER");
788 if (debug && (strstr(debug, "1")))
789 tdm_debug_buffer = 1;
791 debug = getenv("TDM_DEBUG_THREAD");
792 if (debug && (strstr(debug, "1")))
793 tdm_debug_thread = 1;
795 debug = getenv("TDM_DEBUG_MUTEX");
796 if (debug && (strstr(debug, "1")))
799 private_display = calloc(1, sizeof(tdm_private_display));
800 if (!private_display) {
801 ret = TDM_ERROR_OUT_OF_MEMORY;
802 TDM_ERR("'private_display != NULL' failed");
806 if (pthread_mutex_init(&private_display->lock, NULL)) {
807 ret = TDM_ERROR_OPERATION_FAILED;
808 TDM_ERR("mutex init failed: %m");
809 goto failed_mutex_init;
812 ret = tdm_event_loop_init(private_display);
813 if (ret != TDM_ERROR_NONE)
816 ret = tdm_thread_init(private_display);
817 if (ret != TDM_ERROR_NONE)
820 ret = _tdm_display_load_module(private_display);
821 if (ret != TDM_ERROR_NONE)
824 TDM_TRACE_BEGIN(Update_Display);
825 ret = _tdm_display_update_internal(private_display, 0);
827 if (ret != TDM_ERROR_NONE)
830 tdm_event_loop_create_backend_source(private_display);
832 private_display->init_count = 1;
834 g_private_display = private_display;
837 *error = TDM_ERROR_NONE;
839 _pthread_mutex_unlock(&gLock);
841 return (tdm_display *)private_display;
844 _tdm_display_unload_module(private_display);
846 tdm_thread_deinit(private_display);
848 tdm_event_loop_deinit(private_display);
850 pthread_mutex_destroy(&private_display->lock);
852 free(private_display);
855 tdm_debug_buffer = 0;
858 _pthread_mutex_unlock(&gLock);
863 tdm_display_deinit(tdm_display *dpy)
865 tdm_private_display *private_display = dpy;
867 if (!private_display)
870 _pthread_mutex_lock(&gLock);
872 private_display->init_count--;
873 if (private_display->init_count > 0) {
874 _pthread_mutex_unlock(&gLock);
878 _pthread_mutex_lock(&private_display->lock);
880 tdm_thread_deinit(private_display);
881 tdm_event_loop_deinit(private_display);
883 _tdm_display_destroy_private_display(private_display);
884 _tdm_display_unload_module(private_display);
886 tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
888 _pthread_mutex_unlock(&private_display->lock);
890 pthread_mutex_destroy(&private_display->lock);
891 free(private_display);
892 g_private_display = NULL;
894 tdm_debug_buffer = 0;
896 _pthread_mutex_unlock(&gLock);