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_main, link) {
160 LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
165 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
166 tdm_capture_destroy_internal(c);
168 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
169 _tdm_display_destroy_private_layer(l);
171 _tdm_display_destroy_caps_output(&private_output->caps);
173 private_output->stamp = 0;
174 free(private_output);
178 _tdm_display_destroy_private_display(tdm_private_display *private_display)
180 tdm_private_output *o = NULL, *oo = NULL;
181 tdm_private_pp *p = NULL, *pp = NULL;
183 free(private_display->outputs_ptr);
185 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
186 tdm_pp_destroy_internal(p);
188 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
189 _tdm_display_destroy_private_output(o);
191 _tdm_display_destroy_caps_pp(&private_display->caps_pp);
192 _tdm_display_destroy_caps_capture(&private_display->caps_capture);
194 private_display->capabilities = 0;
195 private_display->caps_display.max_layer_count = -1;
199 _tdm_display_update_caps_pp(tdm_private_display *private_display,
202 tdm_func_display *func_display = &private_display->func_display;
204 int bufsize = sizeof(buf);
206 int *len_buf = &bufsize;
210 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
211 return TDM_ERROR_NONE;
213 if (!func_display->display_get_pp_capability) {
214 TDM_ERR("no display_get_pp_capability()");
215 return TDM_ERROR_BAD_MODULE;
218 ret = func_display->display_get_pp_capability(private_display->bdata, caps);
219 if (ret != TDM_ERROR_NONE) {
220 TDM_ERR("display_get_pp_capability() failed");
221 return TDM_ERROR_BAD_MODULE;
224 TDM_DBG("pp capabilities: %x", caps->capabilities);
226 for (i = 0; i < caps->format_count; i++)
227 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
228 TDM_DBG("pp formats: %s", buf);
229 TDM_DBG("pp min : %dx%d", caps->min_w, caps->min_h);
230 TDM_DBG("pp max : %dx%d", caps->max_w, caps->max_h);
231 TDM_DBG("pp align: %d", caps->preferred_align);
233 return TDM_ERROR_NONE;
237 _tdm_display_update_caps_capture(tdm_private_display *private_display,
238 tdm_caps_capture *caps)
240 tdm_func_display *func_display = &private_display->func_display;
242 int bufsize = sizeof(buf);
244 int *len_buf = &bufsize;
248 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
249 return TDM_ERROR_NONE;
251 if (!func_display->display_get_capture_capability) {
252 TDM_ERR("no display_get_capture_capability()");
253 return TDM_ERROR_BAD_MODULE;
256 ret = func_display->display_get_capture_capability(private_display->bdata,
258 if (ret != TDM_ERROR_NONE) {
259 TDM_ERR("display_get_capture_capability() failed");
260 return TDM_ERROR_BAD_MODULE;
264 for (i = 0; i < caps->format_count; i++)
265 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
266 TDM_DBG("capture formats: %s", buf);
268 return TDM_ERROR_NONE;
272 _tdm_display_update_caps_layer(tdm_private_display *private_display,
273 tdm_layer *layer_backend, tdm_caps_layer *caps)
275 tdm_func_layer *func_layer = &private_display->func_layer;
277 int bufsize = sizeof(buf);
279 int *len_buf = &bufsize;
283 if (!func_layer->layer_get_capability) {
284 TDM_ERR("no layer_get_capability()");
285 return TDM_ERROR_BAD_MODULE;
288 ret = func_layer->layer_get_capability(layer_backend, caps);
289 if (ret != TDM_ERROR_NONE) {
290 TDM_ERR("layer_get_capability() failed");
291 return TDM_ERROR_BAD_MODULE;
294 TDM_DBG("layer capabilities: %x", caps->capabilities);
295 TDM_DBG("layer zpos : %d", caps->zpos);
297 for (i = 0; i < caps->format_count; i++)
298 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
299 TDM_DBG("layer formats: %s", buf);
300 for (i = 0; i < caps->prop_count; i++)
301 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
303 return TDM_ERROR_NONE;
307 _tdm_display_update_caps_output(tdm_private_display *private_display, int pipe,
308 tdm_output *output_backend, tdm_caps_output *caps)
310 tdm_func_output *func_output = &private_display->func_output;
311 char temp[TDM_NAME_LEN];
315 if (!func_output->output_get_capability) {
316 TDM_ERR("no output_get_capability()");
317 return TDM_ERROR_BAD_MODULE;
320 ret = func_output->output_get_capability(output_backend, caps);
321 if (ret != TDM_ERROR_NONE) {
322 TDM_ERR("output_get_capability() failed");
323 return TDM_ERROR_BAD_MODULE;
326 /* FIXME: Use model for tdm client to distinguish amoung outputs */
327 snprintf(temp, TDM_NAME_LEN, "%s-%d", caps->model, pipe);
328 snprintf(caps->model, TDM_NAME_LEN, "%s", temp);
330 TDM_DBG("output maker: %s", caps->maker);
331 TDM_DBG("output model: %s", caps->model);
332 TDM_DBG("output name: %s", caps->name);
333 TDM_DBG("output status: %d", caps->status);
334 TDM_DBG("output type : %d", caps->type);
335 for (i = 0; i < caps->prop_count; i++)
336 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
337 for (i = 0; i < caps->mode_count; i++) {
338 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
339 caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
340 caps->modes[i].flags, caps->modes[i].type);
341 TDM_DBG("\t\t %d, %d, %d, %d, %d",
342 caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
343 caps->modes[i].htotal, caps->modes[i].hskew);
344 TDM_DBG("\t\t %d, %d, %d, %d, %d",
345 caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
346 caps->modes[i].vtotal, caps->modes[i].vscan);
348 TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h);
349 TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h);
350 TDM_DBG("output align: %d", caps->preferred_align);
352 return TDM_ERROR_NONE;
356 _tdm_display_update_layer(tdm_private_display *private_display,
357 tdm_private_output *private_output,
358 tdm_layer *layer_backend)
360 tdm_private_layer *private_layer;
363 private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
364 if (!private_layer) {
365 private_layer = calloc(1, sizeof(tdm_private_layer));
366 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
368 LIST_ADD(&private_layer->link, &private_output->layer_list);
369 private_layer->private_display = private_display;
370 private_layer->private_output = private_output;
371 private_layer->layer_backend = layer_backend;
373 LIST_INITHEAD(&private_layer->capture_list);
375 private_layer->usable = 1;
377 _tdm_display_destroy_caps_layer(&private_layer->caps);
379 ret = _tdm_display_update_caps_layer(private_display, layer_backend,
380 &private_layer->caps);
381 if (ret != TDM_ERROR_NONE)
384 return TDM_ERROR_NONE;
386 _tdm_display_destroy_private_layer(private_layer);
391 _tdm_display_update_output(tdm_private_display *private_display,
392 tdm_output *output_backend, int pipe)
394 tdm_func_output *func_output = &private_display->func_output;
395 tdm_private_output *private_output = NULL;
396 tdm_layer **layers = NULL;
397 int layer_count = 0, i;
400 private_output = _tdm_display_find_private_output(private_display,
402 if (!private_output) {
403 private_output = calloc(1, sizeof(tdm_private_output));
404 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
406 private_output->stamp = tdm_helper_get_time_in_millis();
407 while (tdm_display_find_output_stamp(private_display, private_output->stamp))
408 private_output->stamp++;
410 LIST_ADD(&private_output->link, &private_display->output_list);
412 private_output->private_display = private_display;
413 private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF;
414 private_output->output_backend = output_backend;
415 private_output->pipe = pipe;
417 LIST_INITHEAD(&private_output->layer_list);
418 LIST_INITHEAD(&private_output->capture_list);
419 LIST_INITHEAD(&private_output->vblank_handler_list);
420 LIST_INITHEAD(&private_output->commit_handler_list);
421 LIST_INITHEAD(&private_output->change_handler_list_main);
422 LIST_INITHEAD(&private_output->change_handler_list_sub);
424 if (func_output->output_set_status_handler)
425 func_output->output_set_status_handler(private_output->output_backend,
426 tdm_output_cb_status,
430 _tdm_display_destroy_caps_output(&private_output->caps);
432 ret = _tdm_display_update_caps_output(private_display, pipe, output_backend,
433 &private_output->caps);
434 if (ret != TDM_ERROR_NONE)
437 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
438 if (ret != TDM_ERROR_NONE)
441 for (i = 0; i < layer_count; i++) {
442 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
443 if (ret != TDM_ERROR_NONE)
449 return TDM_ERROR_NONE;
451 _tdm_display_destroy_private_output(private_output);
457 _tdm_display_update_internal(tdm_private_display *private_display,
460 tdm_func_display *func_display = &private_display->func_display;
461 tdm_output **outputs = NULL;
462 int output_count = 0, i;
465 LIST_INITHEAD(&private_display->output_list);
466 LIST_INITHEAD(&private_display->pp_list);
467 LIST_INITHEAD(&private_display->capture_list);
470 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
471 if (ret != TDM_ERROR_NONE)
474 ret = _tdm_display_update_caps_capture(private_display,
475 &private_display->caps_capture);
476 if (ret != TDM_ERROR_NONE)
480 outputs = func_display->display_get_outputs(private_display->bdata,
481 &output_count, &ret);
482 if (ret != TDM_ERROR_NONE)
485 for (i = 0; i < output_count; i++) {
486 ret = _tdm_display_update_output(private_display, outputs[i], i);
487 if (ret != TDM_ERROR_NONE)
493 return TDM_ERROR_NONE;
496 _tdm_display_destroy_private_display(private_display);
502 tdm_display_update(tdm_display *dpy)
504 tdm_private_display *private_display;
507 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
509 private_display = dpy;
510 _pthread_mutex_lock(&private_display->lock);
512 ret = _tdm_display_update_internal(private_display, 1);
514 _pthread_mutex_unlock(&private_display->lock);
519 #define SUFFIX_MODULE ".so"
520 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
523 int tdm_debug_buffer;
524 int tdm_debug_thread;
527 static tdm_private_display *g_private_display;
528 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
531 _tdm_display_check_module(tdm_backend_module *module)
538 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
539 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
541 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
543 name = module->name ? module->name : "unknown";
544 vendor = module->vendor ? module->vendor : "unknown";
545 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
546 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
548 TDM_INFO("TDM module name: %s", name);
549 TDM_INFO("'%s' vendor: %s", name, vendor);
550 TDM_INFO("'%s' version: %d.%d", name, major, minor);
552 if (major != abimaj) {
553 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
554 return TDM_ERROR_BAD_MODULE;
557 if (minor > abimin) {
558 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
559 return TDM_ERROR_BAD_MODULE;
563 TDM_ERR("'%s' doesn't have init function", name);
564 return TDM_ERROR_BAD_MODULE;
567 if (!module->deinit) {
568 TDM_ERR("'%s' doesn't have deinit function", name);
569 return TDM_ERROR_BAD_MODULE;
572 return TDM_ERROR_NONE;
576 _tdm_display_check_backend_functions(tdm_private_display *private_display)
578 tdm_func_display *func_display = &private_display->func_display;
579 tdm_func_output *func_output = &private_display->func_output;
580 tdm_func_layer *func_layer = &private_display->func_layer;
583 /* below functions should be implemented in backend side */
585 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
586 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
587 TDM_ERROR_BAD_MODULE);
588 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
589 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
590 TDM_ERROR_BAD_MODULE);
591 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
592 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
594 ret = func_display->display_get_capabilitiy(private_display->bdata,
595 &private_display->caps_display);
596 if (ret != TDM_ERROR_NONE) {
597 TDM_ERR("display_get_capabilitiy() failed");
598 return TDM_ERROR_BAD_MODULE;
601 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
602 tdm_func_pp *func_pp = &private_display->func_pp;
603 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
604 TDM_ERROR_BAD_MODULE);
605 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
606 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
607 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
608 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
611 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
612 tdm_func_capture *func_capture = &private_display->func_capture;
613 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
614 TDM_ERROR_BAD_MODULE);
615 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
616 TDM_ERROR_BAD_MODULE);
617 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
618 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
619 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
620 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
621 TDM_ERROR_BAD_MODULE);
624 return TDM_ERROR_NONE;
628 _tdm_display_load_module_with_file(tdm_private_display *private_display,
631 char path[PATH_MAX] = {0,};
632 tdm_backend_module *module_data;
636 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
638 TDM_TRACE_BEGIN(Load_Backend);
640 module = dlopen(path, RTLD_LAZY);
642 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
644 return TDM_ERROR_BAD_MODULE;
647 module_data = dlsym(module, "tdm_backend_module_data");
649 TDM_ERR("'%s' doesn't have data object", file);
650 ret = TDM_ERROR_BAD_MODULE;
655 private_display->module_data = module_data;
656 private_display->module = module;
658 /* check if version, init() and deinit() are valid or not */
659 ret = _tdm_display_check_module(module_data);
660 if (ret != TDM_ERROR_NONE)
665 /* We don't care if backend_data is NULL or not. It's up to backend. */
666 TDM_TRACE_BEGIN(Init_Backend);
667 private_display->bdata = module_data->init((tdm_display *)private_display,
670 if (ret != TDM_ERROR_NONE) {
671 TDM_ERR("'%s' init failed", file);
675 ret = _tdm_display_check_backend_functions(private_display);
676 if (ret != TDM_ERROR_NONE) {
677 module_data->deinit(private_display->bdata);
678 private_display->bdata = NULL;
682 TDM_INFO("Success to load module(%s)", file);
684 return TDM_ERROR_NONE;
687 private_display->module_data = NULL;
688 private_display->module = NULL;
693 _tdm_display_load_module(tdm_private_display *private_display)
695 const char *module_name;
696 struct dirent **namelist;
700 module_name = getenv("TDM_MODULE");
702 module_name = DEFAULT_MODULE;
704 /* load bufmgr priv from default lib */
705 ret = _tdm_display_load_module_with_file(private_display, module_name);
706 if (ret == TDM_ERROR_NONE)
707 return TDM_ERROR_NONE;
709 /* load bufmgr priv from configured path */
710 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
712 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
713 return TDM_ERROR_BAD_MODULE;
716 ret = TDM_ERROR_BAD_MODULE;
718 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
719 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
729 _tdm_display_unload_module(tdm_private_display *private_display)
731 if (private_display->module_data)
732 private_display->module_data->deinit(private_display->bdata);
733 if (private_display->module)
734 dlclose(private_display->module);
736 private_display->bdata = NULL;
737 private_display->module_data = NULL;
738 private_display->module = NULL;
742 tdm_display_init(tdm_error *error)
744 tdm_private_display *private_display = NULL;
748 _pthread_mutex_lock(&gLock);
750 if (g_private_display) {
751 g_private_display->init_count++;
752 _pthread_mutex_unlock(&gLock);
754 *error = TDM_ERROR_NONE;
755 return g_private_display;
758 debug = getenv("TDM_DEBUG");
759 if (debug && (strstr(debug, "1")))
762 debug = getenv("TDM_DEBUG_BUFFER");
763 if (debug && (strstr(debug, "1")))
764 tdm_debug_buffer = 1;
766 debug = getenv("TDM_DEBUG_THREAD");
767 if (debug && (strstr(debug, "1")))
768 tdm_debug_thread = 1;
770 debug = getenv("TDM_DEBUG_MUTEX");
771 if (debug && (strstr(debug, "1")))
774 private_display = calloc(1, sizeof(tdm_private_display));
775 if (!private_display) {
776 ret = TDM_ERROR_OUT_OF_MEMORY;
777 TDM_ERR("'private_display != NULL' failed");
781 if (pthread_mutex_init(&private_display->lock, NULL)) {
782 ret = TDM_ERROR_OPERATION_FAILED;
783 TDM_ERR("mutex init failed: %m");
784 goto failed_mutex_init;
787 ret = tdm_event_loop_init(private_display);
788 if (ret != TDM_ERROR_NONE)
791 ret = _tdm_display_load_module(private_display);
792 if (ret != TDM_ERROR_NONE)
796 int tdm_drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
797 if (tdm_drm_fd >= 0) {
798 private_display->bufmgr = tbm_bufmgr_init(tdm_drm_fd);
800 if (!private_display->bufmgr) {
801 TDM_ERR("tbm_bufmgr_init failed");
804 TDM_INFO("tbm_bufmgr_init successed");
809 TDM_TRACE_BEGIN(Update_Display);
810 ret = _tdm_display_update_internal(private_display, 0);
812 if (ret != TDM_ERROR_NONE)
815 tdm_event_loop_create_backend_source(private_display);
817 private_display->init_count = 1;
819 g_private_display = private_display;
822 *error = TDM_ERROR_NONE;
824 _pthread_mutex_unlock(&gLock);
826 return (tdm_display *)private_display;
829 _tdm_display_unload_module(private_display);
831 tdm_event_loop_deinit(private_display);
833 pthread_mutex_destroy(&private_display->lock);
835 free(private_display);
838 tdm_debug_buffer = 0;
841 _pthread_mutex_unlock(&gLock);
846 tdm_display_deinit(tdm_display *dpy)
848 tdm_private_display *private_display = dpy;
850 if (!private_display)
853 _pthread_mutex_lock(&gLock);
855 private_display->init_count--;
856 if (private_display->init_count > 0) {
857 _pthread_mutex_unlock(&gLock);
861 _pthread_mutex_lock(&private_display->lock);
863 tdm_event_loop_deinit(private_display);
865 _tdm_display_destroy_private_display(private_display);
866 _tdm_display_unload_module(private_display);
869 if (private_display->bufmgr)
870 tbm_bufmgr_deinit(private_display->bufmgr);
873 tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
875 _pthread_mutex_unlock(&private_display->lock);
877 pthread_mutex_destroy(&private_display->lock);
878 free(private_display);
879 g_private_display = NULL;
881 tdm_debug_buffer = 0;
883 _pthread_mutex_unlock(&gLock);