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 pthread_mutex_t tdm_mutex_check_lock = PTHREAD_MUTEX_INITIALIZER;
48 static tdm_private_layer *
49 _tdm_display_find_private_layer(tdm_private_output *private_output,
50 tdm_layer *layer_backend)
52 tdm_private_layer *private_layer = NULL;
54 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
55 if (private_layer->layer_backend == layer_backend)
62 static tdm_private_output *
63 _tdm_display_find_private_output(tdm_private_display *private_display,
64 tdm_output *output_backend)
66 tdm_private_output *private_output = NULL;
68 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
69 if (private_output->output_backend == output_backend)
70 return private_output;
76 INTERN tdm_private_output *
77 tdm_display_find_output_stamp(tdm_private_display *private_display,
80 tdm_private_output *private_output = NULL;
82 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
83 if (private_output->stamp == stamp)
84 return private_output;
91 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
93 free(caps_pp->formats);
94 memset(caps_pp, 0, sizeof(tdm_caps_pp));
98 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
100 free(caps_capture->formats);
101 memset(caps_capture, 0, sizeof(tdm_caps_capture));
105 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
107 free(caps_layer->formats);
108 free(caps_layer->props);
109 memset(caps_layer, 0, sizeof(tdm_caps_layer));
113 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
115 free(caps_output->modes);
116 free(caps_output->props);
117 memset(caps_output, 0, sizeof(tdm_caps_output));
121 _tdm_display_destroy_private_layer(tdm_private_layer *private_layer)
123 tdm_private_capture *c = NULL, *cc = NULL;
125 LIST_DEL(&private_layer->link);
127 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link)
128 tdm_capture_destroy_internal(c);
130 _tdm_display_destroy_caps_layer(&private_layer->caps);
136 _tdm_display_destroy_private_output(tdm_private_output *private_output)
138 tdm_private_layer *l = NULL, *ll = NULL;
139 tdm_private_capture *c = NULL, *cc = NULL;
140 tdm_private_vblank_handler *v = NULL, *vv = NULL;
141 tdm_private_commit_handler *m = NULL, *mm = NULL;
142 tdm_private_change_handler *h = NULL, *hh = NULL;
144 LIST_DEL(&private_output->link);
146 free(private_output->layers_ptr);
148 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
153 LIST_FOR_EACH_ENTRY_SAFE(m, mm, &private_output->commit_handler_list, link) {
158 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
163 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
168 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
169 tdm_capture_destroy_internal(c);
171 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
172 _tdm_display_destroy_private_layer(l);
174 _tdm_display_destroy_caps_output(&private_output->caps);
176 private_output->stamp = 0;
177 free(private_output);
181 _tdm_display_destroy_private_display(tdm_private_display *private_display)
183 tdm_private_output *o = NULL, *oo = NULL;
184 tdm_private_pp *p = NULL, *pp = NULL;
186 free(private_display->outputs_ptr);
188 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
189 tdm_pp_destroy_internal(p);
191 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
192 _tdm_display_destroy_private_output(o);
194 _tdm_display_destroy_caps_pp(&private_display->caps_pp);
195 _tdm_display_destroy_caps_capture(&private_display->caps_capture);
197 private_display->capabilities = 0;
198 private_display->caps_display.max_layer_count = -1;
202 _tdm_display_update_caps_pp(tdm_private_display *private_display,
205 tdm_func_display *func_display = &private_display->func_display;
207 int bufsize = sizeof(buf);
209 int *len_buf = &bufsize;
213 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
214 return TDM_ERROR_NONE;
216 if (!func_display->display_get_pp_capability) {
217 TDM_ERR("no display_get_pp_capability()");
218 return TDM_ERROR_BAD_MODULE;
221 ret = func_display->display_get_pp_capability(private_display->bdata, caps);
222 if (ret != TDM_ERROR_NONE) {
223 TDM_ERR("display_get_pp_capability() failed");
224 return TDM_ERROR_BAD_MODULE;
227 TDM_DBG("pp capabilities: %x", caps->capabilities);
229 for (i = 0; i < caps->format_count; i++)
230 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
231 TDM_DBG("pp formats: %s", buf);
232 TDM_DBG("pp min : %dx%d", caps->min_w, caps->min_h);
233 TDM_DBG("pp max : %dx%d", caps->max_w, caps->max_h);
234 TDM_DBG("pp align: %d", caps->preferred_align);
236 return TDM_ERROR_NONE;
240 _tdm_display_update_caps_capture(tdm_private_display *private_display,
241 tdm_caps_capture *caps)
243 tdm_func_display *func_display = &private_display->func_display;
245 int bufsize = sizeof(buf);
247 int *len_buf = &bufsize;
251 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
252 return TDM_ERROR_NONE;
254 if (!func_display->display_get_capture_capability) {
255 TDM_ERR("no display_get_capture_capability()");
256 return TDM_ERROR_BAD_MODULE;
259 ret = func_display->display_get_capture_capability(private_display->bdata,
261 if (ret != TDM_ERROR_NONE) {
262 TDM_ERR("display_get_capture_capability() failed");
263 return TDM_ERROR_BAD_MODULE;
267 for (i = 0; i < caps->format_count; i++)
268 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
269 TDM_DBG("capture formats: %s", buf);
271 return TDM_ERROR_NONE;
275 _tdm_display_update_caps_layer(tdm_private_display *private_display,
276 tdm_layer *layer_backend, tdm_caps_layer *caps)
278 tdm_func_layer *func_layer = &private_display->func_layer;
280 int bufsize = sizeof(buf);
282 int *len_buf = &bufsize;
286 if (!func_layer->layer_get_capability) {
287 TDM_ERR("no layer_get_capability()");
288 return TDM_ERROR_BAD_MODULE;
291 ret = func_layer->layer_get_capability(layer_backend, caps);
292 if (ret != TDM_ERROR_NONE) {
293 TDM_ERR("layer_get_capability() failed");
294 return TDM_ERROR_BAD_MODULE;
297 TDM_DBG("layer capabilities: %x", caps->capabilities);
298 TDM_DBG("layer zpos : %d", caps->zpos);
300 for (i = 0; i < caps->format_count; i++)
301 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
302 TDM_DBG("layer formats: %s", buf);
303 for (i = 0; i < caps->prop_count; i++)
304 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
306 return TDM_ERROR_NONE;
310 _tdm_display_update_caps_output(tdm_private_display *private_display, int pipe,
311 tdm_output *output_backend, tdm_caps_output *caps)
313 tdm_func_output *func_output = &private_display->func_output;
314 char temp[TDM_NAME_LEN];
318 if (!func_output->output_get_capability) {
319 TDM_ERR("no output_get_capability()");
320 return TDM_ERROR_BAD_MODULE;
323 ret = func_output->output_get_capability(output_backend, caps);
324 if (ret != TDM_ERROR_NONE) {
325 TDM_ERR("output_get_capability() failed");
326 return TDM_ERROR_BAD_MODULE;
329 /* FIXME: Use model for tdm client to distinguish amoung outputs */
330 snprintf(temp, TDM_NAME_LEN, "%s-%d", caps->model, pipe);
331 snprintf(caps->model, TDM_NAME_LEN, "%s", temp);
333 TDM_DBG("output maker: %s", caps->maker);
334 TDM_DBG("output model: %s", caps->model);
335 TDM_DBG("output name: %s", caps->name);
336 TDM_DBG("output status: %d", caps->status);
337 TDM_DBG("output type : %d", caps->type);
338 for (i = 0; i < caps->prop_count; i++)
339 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
340 for (i = 0; i < caps->mode_count; i++) {
341 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
342 caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
343 caps->modes[i].flags, caps->modes[i].type);
344 TDM_DBG("\t\t %d, %d, %d, %d, %d",
345 caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
346 caps->modes[i].htotal, caps->modes[i].hskew);
347 TDM_DBG("\t\t %d, %d, %d, %d, %d",
348 caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
349 caps->modes[i].vtotal, caps->modes[i].vscan);
351 TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h);
352 TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h);
353 TDM_DBG("output align: %d", caps->preferred_align);
355 return TDM_ERROR_NONE;
359 _tdm_display_update_layer(tdm_private_display *private_display,
360 tdm_private_output *private_output,
361 tdm_layer *layer_backend)
363 tdm_private_layer *private_layer;
366 private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
367 if (!private_layer) {
368 private_layer = calloc(1, sizeof(tdm_private_layer));
369 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
371 LIST_ADD(&private_layer->link, &private_output->layer_list);
372 private_layer->private_display = private_display;
373 private_layer->private_output = private_output;
374 private_layer->layer_backend = layer_backend;
376 LIST_INITHEAD(&private_layer->capture_list);
378 private_layer->usable = 1;
380 _tdm_display_destroy_caps_layer(&private_layer->caps);
382 ret = _tdm_display_update_caps_layer(private_display, layer_backend,
383 &private_layer->caps);
384 if (ret != TDM_ERROR_NONE)
387 return TDM_ERROR_NONE;
389 _tdm_display_destroy_private_layer(private_layer);
394 _tdm_display_update_output(tdm_private_display *private_display,
395 tdm_output *output_backend, int pipe)
397 tdm_func_output *func_output = &private_display->func_output;
398 tdm_private_output *private_output = NULL;
399 tdm_layer **layers = NULL;
400 int layer_count = 0, i;
403 private_output = _tdm_display_find_private_output(private_display,
405 if (!private_output) {
406 private_output = calloc(1, sizeof(tdm_private_output));
407 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
409 private_output->stamp = tdm_helper_get_time_in_millis();
410 while (tdm_display_find_output_stamp(private_display, private_output->stamp))
411 private_output->stamp++;
413 LIST_ADD(&private_output->link, &private_display->output_list);
415 private_output->private_display = private_display;
416 private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF;
417 private_output->output_backend = output_backend;
418 private_output->pipe = pipe;
420 LIST_INITHEAD(&private_output->layer_list);
421 LIST_INITHEAD(&private_output->capture_list);
422 LIST_INITHEAD(&private_output->vblank_handler_list);
423 LIST_INITHEAD(&private_output->commit_handler_list);
424 LIST_INITHEAD(&private_output->change_handler_list_main);
425 LIST_INITHEAD(&private_output->change_handler_list_sub);
427 if (func_output->output_set_status_handler)
428 func_output->output_set_status_handler(private_output->output_backend,
429 tdm_output_cb_status,
433 _tdm_display_destroy_caps_output(&private_output->caps);
435 ret = _tdm_display_update_caps_output(private_display, pipe, output_backend,
436 &private_output->caps);
437 if (ret != TDM_ERROR_NONE)
440 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
441 if (ret != TDM_ERROR_NONE)
444 for (i = 0; i < layer_count; i++) {
445 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
446 if (ret != TDM_ERROR_NONE)
452 return TDM_ERROR_NONE;
454 _tdm_display_destroy_private_output(private_output);
460 _tdm_display_update_internal(tdm_private_display *private_display,
463 tdm_func_display *func_display = &private_display->func_display;
464 tdm_output **outputs = NULL;
465 int output_count = 0, i;
468 LIST_INITHEAD(&private_display->output_list);
469 LIST_INITHEAD(&private_display->pp_list);
470 LIST_INITHEAD(&private_display->capture_list);
473 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
474 if (ret != TDM_ERROR_NONE)
477 ret = _tdm_display_update_caps_capture(private_display,
478 &private_display->caps_capture);
479 if (ret != TDM_ERROR_NONE)
483 outputs = func_display->display_get_outputs(private_display->bdata,
484 &output_count, &ret);
485 if (ret != TDM_ERROR_NONE)
488 for (i = 0; i < output_count; i++) {
489 ret = _tdm_display_update_output(private_display, outputs[i], i);
490 if (ret != TDM_ERROR_NONE)
496 return TDM_ERROR_NONE;
499 _tdm_display_destroy_private_display(private_display);
505 tdm_display_update(tdm_display *dpy)
507 tdm_private_display *private_display;
510 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
512 private_display = dpy;
513 _pthread_mutex_lock(&private_display->lock);
515 ret = _tdm_display_update_internal(private_display, 1);
517 _pthread_mutex_unlock(&private_display->lock);
522 #define SUFFIX_MODULE ".so"
523 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
526 int tdm_debug_buffer;
527 int tdm_debug_thread;
530 static tdm_private_display *g_private_display;
531 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
534 _tdm_display_check_module(tdm_backend_module *module)
541 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
542 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
544 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
546 name = module->name ? module->name : "unknown";
547 vendor = module->vendor ? module->vendor : "unknown";
548 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
549 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
551 TDM_INFO("TDM module name: %s", name);
552 TDM_INFO("'%s' vendor: %s", name, vendor);
553 TDM_INFO("'%s' version: %d.%d", name, major, minor);
555 if (major != abimaj) {
556 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
557 return TDM_ERROR_BAD_MODULE;
560 if (minor > abimin) {
561 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
562 return TDM_ERROR_BAD_MODULE;
566 TDM_ERR("'%s' doesn't have init function", name);
567 return TDM_ERROR_BAD_MODULE;
570 if (!module->deinit) {
571 TDM_ERR("'%s' doesn't have deinit function", name);
572 return TDM_ERROR_BAD_MODULE;
575 return TDM_ERROR_NONE;
579 _tdm_display_check_backend_functions(tdm_private_display *private_display)
581 tdm_func_display *func_display = &private_display->func_display;
582 tdm_func_output *func_output = &private_display->func_output;
583 tdm_func_layer *func_layer = &private_display->func_layer;
586 /* below functions should be implemented in backend side */
588 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
589 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
590 TDM_ERROR_BAD_MODULE);
591 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
592 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
593 TDM_ERROR_BAD_MODULE);
594 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
595 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
597 ret = func_display->display_get_capabilitiy(private_display->bdata,
598 &private_display->caps_display);
599 if (ret != TDM_ERROR_NONE) {
600 TDM_ERR("display_get_capabilitiy() failed");
601 return TDM_ERROR_BAD_MODULE;
604 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
605 tdm_func_pp *func_pp = &private_display->func_pp;
606 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
607 TDM_ERROR_BAD_MODULE);
608 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
609 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
610 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
611 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
614 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
615 tdm_func_capture *func_capture = &private_display->func_capture;
616 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
617 TDM_ERROR_BAD_MODULE);
618 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
619 TDM_ERROR_BAD_MODULE);
620 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
621 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
622 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
623 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
624 TDM_ERROR_BAD_MODULE);
627 return TDM_ERROR_NONE;
631 _tdm_display_load_module_with_file(tdm_private_display *private_display,
634 char path[PATH_MAX] = {0,};
635 tdm_backend_module *module_data;
639 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
641 TDM_TRACE_BEGIN(Load_Backend);
643 module = dlopen(path, RTLD_LAZY);
645 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
647 return TDM_ERROR_BAD_MODULE;
650 module_data = dlsym(module, "tdm_backend_module_data");
652 TDM_ERR("'%s' doesn't have data object", file);
653 ret = TDM_ERROR_BAD_MODULE;
658 private_display->module_data = module_data;
659 private_display->module = module;
661 /* check if version, init() and deinit() are valid or not */
662 ret = _tdm_display_check_module(module_data);
663 if (ret != TDM_ERROR_NONE)
668 /* We don't care if backend_data is NULL or not. It's up to backend. */
669 TDM_TRACE_BEGIN(Init_Backend);
670 private_display->bdata = module_data->init((tdm_display *)private_display,
673 if (ret != TDM_ERROR_NONE) {
674 TDM_ERR("'%s' init failed", file);
678 ret = _tdm_display_check_backend_functions(private_display);
679 if (ret != TDM_ERROR_NONE) {
680 module_data->deinit(private_display->bdata);
681 private_display->bdata = NULL;
685 TDM_INFO("Success to load module(%s)", file);
687 return TDM_ERROR_NONE;
690 private_display->module_data = NULL;
691 private_display->module = NULL;
696 _tdm_display_load_module(tdm_private_display *private_display)
698 const char *module_name;
699 struct dirent **namelist;
703 module_name = getenv("TDM_MODULE");
705 module_name = DEFAULT_MODULE;
707 /* load bufmgr priv from default lib */
708 ret = _tdm_display_load_module_with_file(private_display, module_name);
709 if (ret == TDM_ERROR_NONE)
710 return TDM_ERROR_NONE;
712 /* load bufmgr priv from configured path */
713 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
715 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
716 return TDM_ERROR_BAD_MODULE;
719 ret = TDM_ERROR_BAD_MODULE;
721 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
722 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
732 _tdm_display_unload_module(tdm_private_display *private_display)
734 if (private_display->module_data)
735 private_display->module_data->deinit(private_display->bdata);
736 if (private_display->module)
737 dlclose(private_display->module);
739 private_display->bdata = NULL;
740 private_display->module_data = NULL;
741 private_display->module = NULL;
745 tdm_display_init(tdm_error *error)
747 tdm_private_display *private_display = NULL;
751 _pthread_mutex_lock(&gLock);
753 if (g_private_display) {
754 g_private_display->init_count++;
755 _pthread_mutex_unlock(&gLock);
757 *error = TDM_ERROR_NONE;
758 return g_private_display;
761 debug = getenv("TDM_DEBUG");
762 if (debug && (strstr(debug, "1")))
765 debug = getenv("TDM_DEBUG_BUFFER");
766 if (debug && (strstr(debug, "1")))
767 tdm_debug_buffer = 1;
769 debug = getenv("TDM_DEBUG_THREAD");
770 if (debug && (strstr(debug, "1")))
771 tdm_debug_thread = 1;
773 debug = getenv("TDM_DEBUG_MUTEX");
774 if (debug && (strstr(debug, "1")))
777 private_display = calloc(1, sizeof(tdm_private_display));
778 if (!private_display) {
779 ret = TDM_ERROR_OUT_OF_MEMORY;
780 TDM_ERR("'private_display != NULL' failed");
784 if (pthread_mutex_init(&private_display->lock, NULL)) {
785 ret = TDM_ERROR_OPERATION_FAILED;
786 TDM_ERR("mutex init failed: %m");
787 goto failed_mutex_init;
790 _pthread_mutex_lock(&private_display->lock);
792 ret = tdm_event_loop_init(private_display);
793 if (ret != TDM_ERROR_NONE)
796 ret = _tdm_display_load_module(private_display);
797 if (ret != TDM_ERROR_NONE)
801 int tdm_drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
802 if (tdm_drm_fd >= 0) {
803 private_display->bufmgr = tbm_bufmgr_init(tdm_drm_fd);
805 if (!private_display->bufmgr) {
806 TDM_ERR("tbm_bufmgr_init failed");
809 TDM_INFO("tbm_bufmgr_init successed");
814 TDM_TRACE_BEGIN(Update_Display);
815 ret = _tdm_display_update_internal(private_display, 0);
817 if (ret != TDM_ERROR_NONE)
820 tdm_event_loop_create_backend_source(private_display);
822 private_display->init_count = 1;
824 g_private_display = private_display;
827 *error = TDM_ERROR_NONE;
829 _pthread_mutex_unlock(&private_display->lock);
830 _pthread_mutex_unlock(&gLock);
832 return (tdm_display *)private_display;
835 _tdm_display_unload_module(private_display);
837 tdm_event_loop_deinit(private_display);
839 _pthread_mutex_unlock(&private_display->lock);
840 pthread_mutex_destroy(&private_display->lock);
842 free(private_display);
845 tdm_debug_buffer = 0;
848 _pthread_mutex_unlock(&gLock);
853 tdm_display_deinit(tdm_display *dpy)
855 tdm_private_display *private_display = dpy;
857 if (!private_display)
860 _pthread_mutex_lock(&gLock);
862 private_display->init_count--;
863 if (private_display->init_count > 0) {
864 _pthread_mutex_unlock(&gLock);
868 _pthread_mutex_lock(&private_display->lock);
870 tdm_event_loop_deinit(private_display);
872 _tdm_display_destroy_private_display(private_display);
873 _tdm_display_unload_module(private_display);
876 if (private_display->bufmgr)
877 tbm_bufmgr_deinit(private_display->bufmgr);
880 tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
882 _pthread_mutex_unlock(&private_display->lock);
884 pthread_mutex_destroy(&private_display->lock);
885 free(private_display);
886 g_private_display = NULL;
888 tdm_debug_buffer = 0;
890 _pthread_mutex_unlock(&gLock);