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->output_backend = output_backend;
414 private_output->pipe = pipe;
416 LIST_INITHEAD(&private_output->layer_list);
417 LIST_INITHEAD(&private_output->capture_list);
418 LIST_INITHEAD(&private_output->vblank_handler_list);
419 LIST_INITHEAD(&private_output->commit_handler_list);
420 LIST_INITHEAD(&private_output->change_handler_list_main);
421 LIST_INITHEAD(&private_output->change_handler_list_sub);
423 if (func_output->output_set_status_handler)
424 func_output->output_set_status_handler(private_output->output_backend,
425 tdm_output_cb_status,
429 _tdm_display_destroy_caps_output(&private_output->caps);
431 ret = _tdm_display_update_caps_output(private_display, pipe, output_backend,
432 &private_output->caps);
433 if (ret != TDM_ERROR_NONE)
436 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
437 if (ret != TDM_ERROR_NONE)
440 for (i = 0; i < layer_count; i++) {
441 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
442 if (ret != TDM_ERROR_NONE)
448 return TDM_ERROR_NONE;
450 _tdm_display_destroy_private_output(private_output);
456 _tdm_display_update_internal(tdm_private_display *private_display,
459 tdm_func_display *func_display = &private_display->func_display;
460 tdm_output **outputs = NULL;
461 int output_count = 0, i;
464 LIST_INITHEAD(&private_display->output_list);
465 LIST_INITHEAD(&private_display->pp_list);
466 LIST_INITHEAD(&private_display->capture_list);
469 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
470 if (ret != TDM_ERROR_NONE)
473 ret = _tdm_display_update_caps_capture(private_display,
474 &private_display->caps_capture);
475 if (ret != TDM_ERROR_NONE)
479 outputs = func_display->display_get_outputs(private_display->bdata,
480 &output_count, &ret);
481 if (ret != TDM_ERROR_NONE)
484 for (i = 0; i < output_count; i++) {
485 ret = _tdm_display_update_output(private_display, outputs[i], i);
486 if (ret != TDM_ERROR_NONE)
492 return TDM_ERROR_NONE;
495 _tdm_display_destroy_private_display(private_display);
501 tdm_display_update(tdm_display *dpy)
503 tdm_private_display *private_display;
506 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
508 private_display = dpy;
509 _pthread_mutex_lock(&private_display->lock);
511 ret = _tdm_display_update_internal(private_display, 1);
513 _pthread_mutex_unlock(&private_display->lock);
518 #define SUFFIX_MODULE ".so"
519 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
522 int tdm_debug_buffer;
523 int tdm_debug_thread;
526 static tdm_private_display *g_private_display;
527 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
530 _tdm_display_check_module(tdm_backend_module *module)
537 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
538 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
540 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
542 name = module->name ? module->name : "unknown";
543 vendor = module->vendor ? module->vendor : "unknown";
544 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
545 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
547 TDM_INFO("TDM module name: %s", name);
548 TDM_INFO("'%s' vendor: %s", name, vendor);
549 TDM_INFO("'%s' version: %d.%d", name, major, minor);
551 if (major != abimaj) {
552 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
553 return TDM_ERROR_BAD_MODULE;
556 if (minor > abimin) {
557 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
558 return TDM_ERROR_BAD_MODULE;
562 TDM_ERR("'%s' doesn't have init function", name);
563 return TDM_ERROR_BAD_MODULE;
566 if (!module->deinit) {
567 TDM_ERR("'%s' doesn't have deinit function", name);
568 return TDM_ERROR_BAD_MODULE;
571 return TDM_ERROR_NONE;
575 _tdm_display_check_backend_functions(tdm_private_display *private_display)
577 tdm_func_display *func_display = &private_display->func_display;
578 tdm_func_output *func_output = &private_display->func_output;
579 tdm_func_layer *func_layer = &private_display->func_layer;
582 /* below functions should be implemented in backend side */
584 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
585 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
586 TDM_ERROR_BAD_MODULE);
587 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
588 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
589 TDM_ERROR_BAD_MODULE);
590 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
591 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
593 ret = func_display->display_get_capabilitiy(private_display->bdata,
594 &private_display->caps_display);
595 if (ret != TDM_ERROR_NONE) {
596 TDM_ERR("display_get_capabilitiy() failed");
597 return TDM_ERROR_BAD_MODULE;
600 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
601 tdm_func_pp *func_pp = &private_display->func_pp;
602 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
603 TDM_ERROR_BAD_MODULE);
604 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
605 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
606 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
607 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
610 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
611 tdm_func_capture *func_capture = &private_display->func_capture;
612 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
613 TDM_ERROR_BAD_MODULE);
614 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
615 TDM_ERROR_BAD_MODULE);
616 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
617 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
618 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
619 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
620 TDM_ERROR_BAD_MODULE);
623 return TDM_ERROR_NONE;
627 _tdm_display_load_module_with_file(tdm_private_display *private_display,
630 char path[PATH_MAX] = {0,};
631 tdm_backend_module *module_data;
635 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
637 TDM_TRACE_BEGIN(Load_Backend);
639 module = dlopen(path, RTLD_LAZY);
641 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
643 return TDM_ERROR_BAD_MODULE;
646 module_data = dlsym(module, "tdm_backend_module_data");
648 TDM_ERR("'%s' doesn't have data object", file);
649 ret = TDM_ERROR_BAD_MODULE;
654 private_display->module_data = module_data;
655 private_display->module = module;
657 /* check if version, init() and deinit() are valid or not */
658 ret = _tdm_display_check_module(module_data);
659 if (ret != TDM_ERROR_NONE)
664 /* We don't care if backend_data is NULL or not. It's up to backend. */
665 TDM_TRACE_BEGIN(Init_Backend);
666 private_display->bdata = module_data->init((tdm_display *)private_display,
669 if (ret != TDM_ERROR_NONE) {
670 TDM_ERR("'%s' init failed", file);
674 ret = _tdm_display_check_backend_functions(private_display);
675 if (ret != TDM_ERROR_NONE) {
676 module_data->deinit(private_display->bdata);
677 private_display->bdata = NULL;
681 TDM_INFO("Success to load module(%s)", file);
683 return TDM_ERROR_NONE;
686 private_display->module_data = NULL;
687 private_display->module = NULL;
692 _tdm_display_load_module(tdm_private_display *private_display)
694 const char *module_name;
695 struct dirent **namelist;
699 module_name = getenv("TDM_MODULE");
701 module_name = DEFAULT_MODULE;
703 /* load bufmgr priv from default lib */
704 ret = _tdm_display_load_module_with_file(private_display, module_name);
705 if (ret == TDM_ERROR_NONE)
706 return TDM_ERROR_NONE;
708 /* load bufmgr priv from configured path */
709 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
711 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
712 return TDM_ERROR_BAD_MODULE;
715 ret = TDM_ERROR_BAD_MODULE;
717 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
718 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
728 _tdm_display_unload_module(tdm_private_display *private_display)
730 if (private_display->module_data)
731 private_display->module_data->deinit(private_display->bdata);
732 if (private_display->module)
733 dlclose(private_display->module);
735 private_display->bdata = NULL;
736 private_display->module_data = NULL;
737 private_display->module = NULL;
741 tdm_display_init(tdm_error *error)
743 tdm_private_display *private_display = NULL;
747 _pthread_mutex_lock(&gLock);
749 if (g_private_display) {
750 g_private_display->init_count++;
751 _pthread_mutex_unlock(&gLock);
753 *error = TDM_ERROR_NONE;
754 return g_private_display;
757 debug = getenv("TDM_DEBUG");
758 if (debug && (strstr(debug, "1")))
761 debug = getenv("TDM_DEBUG_BUFFER");
762 if (debug && (strstr(debug, "1")))
763 tdm_debug_buffer = 1;
765 debug = getenv("TDM_DEBUG_THREAD");
766 if (debug && (strstr(debug, "1")))
767 tdm_debug_thread = 1;
769 debug = getenv("TDM_DEBUG_MUTEX");
770 if (debug && (strstr(debug, "1")))
773 private_display = calloc(1, sizeof(tdm_private_display));
774 if (!private_display) {
775 ret = TDM_ERROR_OUT_OF_MEMORY;
776 TDM_ERR("'private_display != NULL' failed");
780 if (pthread_mutex_init(&private_display->lock, NULL)) {
781 ret = TDM_ERROR_OPERATION_FAILED;
782 TDM_ERR("mutex init failed: %m");
783 goto failed_mutex_init;
786 ret = tdm_event_loop_init(private_display);
787 if (ret != TDM_ERROR_NONE)
790 ret = _tdm_display_load_module(private_display);
791 if (ret != TDM_ERROR_NONE)
795 int tdm_drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
796 if (tdm_drm_fd >= 0) {
797 private_display->bufmgr = tbm_bufmgr_init(tdm_drm_fd);
798 if (!private_display->bufmgr) {
799 TDM_ERR("tbm_bufmgr_init failed");
802 TDM_INFO("tbm_bufmgr_init successed");
807 TDM_TRACE_BEGIN(Update_Display);
808 ret = _tdm_display_update_internal(private_display, 0);
810 if (ret != TDM_ERROR_NONE)
813 tdm_event_loop_create_backend_source(private_display);
815 private_display->init_count = 1;
817 g_private_display = private_display;
820 *error = TDM_ERROR_NONE;
822 _pthread_mutex_unlock(&gLock);
824 return (tdm_display *)private_display;
827 _tdm_display_unload_module(private_display);
829 tdm_event_loop_deinit(private_display);
831 pthread_mutex_destroy(&private_display->lock);
833 free(private_display);
836 tdm_debug_buffer = 0;
839 _pthread_mutex_unlock(&gLock);
844 tdm_display_deinit(tdm_display *dpy)
846 tdm_private_display *private_display = dpy;
848 if (!private_display)
851 _pthread_mutex_lock(&gLock);
853 private_display->init_count--;
854 if (private_display->init_count > 0) {
855 _pthread_mutex_unlock(&gLock);
859 _pthread_mutex_lock(&private_display->lock);
861 tdm_event_loop_deinit(private_display);
863 _tdm_display_destroy_private_display(private_display);
864 _tdm_display_unload_module(private_display);
867 if (private_display->bufmgr)
868 tbm_bufmgr_deinit(private_display->bufmgr);
871 tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
873 _pthread_mutex_unlock(&private_display->lock);
875 pthread_mutex_destroy(&private_display->lock);
876 free(private_display);
877 g_private_display = NULL;
879 tdm_debug_buffer = 0;
881 _pthread_mutex_unlock(&gLock);