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;
74 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
76 free(caps_pp->formats);
77 memset(caps_pp, 0, sizeof(tdm_caps_pp));
81 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
83 free(caps_capture->formats);
84 memset(caps_capture, 0, sizeof(tdm_caps_capture));
88 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
90 free(caps_layer->formats);
91 free(caps_layer->props);
92 memset(caps_layer, 0, sizeof(tdm_caps_layer));
96 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
98 free(caps_output->modes);
99 free(caps_output->props);
100 memset(caps_output, 0, sizeof(tdm_caps_output));
104 _tdm_display_destroy_private_layer(tdm_private_layer *private_layer)
106 tdm_private_capture *c = NULL, *cc = NULL;
108 LIST_DEL(&private_layer->link);
110 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link)
111 tdm_capture_destroy_internal(c);
113 _tdm_display_destroy_caps_layer(&private_layer->caps);
119 _tdm_display_destroy_private_output(tdm_private_output *private_output)
121 tdm_private_layer *l = NULL, *ll = NULL;
122 tdm_private_capture *c = NULL, *cc = NULL;
123 tdm_private_vblank_handler *v = NULL, *vv = NULL;
124 tdm_private_commit_handler *m = NULL, *mm = NULL;
126 LIST_DEL(&private_output->link);
128 free(private_output->layers_ptr);
130 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
135 LIST_FOR_EACH_ENTRY_SAFE(m, mm, &private_output->commit_handler_list, link) {
140 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
141 tdm_capture_destroy_internal(c);
143 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
144 _tdm_display_destroy_private_layer(l);
146 _tdm_display_destroy_caps_output(&private_output->caps);
148 free(private_output);
152 _tdm_display_destroy_private_display(tdm_private_display *private_display)
154 tdm_private_output *o = NULL, *oo = NULL;
155 tdm_private_pp *p = NULL, *pp = NULL;
157 free(private_display->outputs_ptr);
159 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
160 tdm_pp_destroy_internal(p);
162 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
163 _tdm_display_destroy_private_output(o);
165 _tdm_display_destroy_caps_pp(&private_display->caps_pp);
166 _tdm_display_destroy_caps_capture(&private_display->caps_capture);
168 private_display->capabilities = 0;
169 private_display->caps_display.max_layer_count = -1;
173 _tdm_display_update_caps_pp(tdm_private_display *private_display,
176 tdm_func_display *func_display = &private_display->func_display;
178 int bufsize = sizeof(buf);
180 int *len_buf = &bufsize;
184 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
185 return TDM_ERROR_NONE;
187 if (!func_display->display_get_pp_capability) {
188 TDM_ERR("no display_get_pp_capability()");
189 return TDM_ERROR_BAD_MODULE;
192 ret = func_display->display_get_pp_capability(private_display->bdata, caps);
193 if (ret != TDM_ERROR_NONE) {
194 TDM_ERR("display_get_pp_capability() failed");
195 return TDM_ERROR_BAD_MODULE;
198 TDM_DBG("pp capabilities: %x", caps->capabilities);
200 for (i = 0; i < caps->format_count; i++)
201 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
202 TDM_DBG("pp formats: %s", buf);
203 TDM_DBG("pp min : %dx%d", caps->min_w, caps->min_h);
204 TDM_DBG("pp max : %dx%d", caps->max_w, caps->max_h);
205 TDM_DBG("pp align: %d", caps->preferred_align);
207 return TDM_ERROR_NONE;
211 _tdm_display_update_caps_capture(tdm_private_display *private_display,
212 tdm_caps_capture *caps)
214 tdm_func_display *func_display = &private_display->func_display;
216 int bufsize = sizeof(buf);
218 int *len_buf = &bufsize;
222 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
223 return TDM_ERROR_NONE;
225 if (!func_display->display_get_capture_capability) {
226 TDM_ERR("no display_get_capture_capability()");
227 return TDM_ERROR_BAD_MODULE;
230 ret = func_display->display_get_capture_capability(private_display->bdata,
232 if (ret != TDM_ERROR_NONE) {
233 TDM_ERR("display_get_capture_capability() failed");
234 return TDM_ERROR_BAD_MODULE;
238 for (i = 0; i < caps->format_count; i++)
239 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
240 TDM_DBG("capture formats: %s", buf);
242 return TDM_ERROR_NONE;
246 _tdm_display_update_caps_layer(tdm_private_display *private_display,
247 tdm_layer *layer_backend, tdm_caps_layer *caps)
249 tdm_func_layer *func_layer = &private_display->func_layer;
251 int bufsize = sizeof(buf);
253 int *len_buf = &bufsize;
257 if (!func_layer->layer_get_capability) {
258 TDM_ERR("no layer_get_capability()");
259 return TDM_ERROR_BAD_MODULE;
262 ret = func_layer->layer_get_capability(layer_backend, caps);
263 if (ret != TDM_ERROR_NONE) {
264 TDM_ERR("layer_get_capability() failed");
265 return TDM_ERROR_BAD_MODULE;
268 TDM_DBG("layer capabilities: %x", caps->capabilities);
269 TDM_DBG("layer zpos : %d", caps->zpos);
271 for (i = 0; i < caps->format_count; i++)
272 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
273 TDM_DBG("layer formats: %s", buf);
274 for (i = 0; i < caps->prop_count; i++)
275 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
277 return TDM_ERROR_NONE;
281 _tdm_display_update_caps_output(tdm_private_display *private_display,
282 tdm_output *output_backend, tdm_caps_output *caps)
284 tdm_func_output *func_output = &private_display->func_output;
288 if (!func_output->output_get_capability) {
289 TDM_ERR("no output_get_capability()");
290 return TDM_ERROR_BAD_MODULE;
293 ret = func_output->output_get_capability(output_backend, caps);
294 if (ret != TDM_ERROR_NONE) {
295 TDM_ERR("output_get_capability() failed");
296 return TDM_ERROR_BAD_MODULE;
299 TDM_DBG("output maker: %s", caps->maker);
300 TDM_DBG("output model: %s", caps->model);
301 TDM_DBG("output name: %s", caps->name);
302 TDM_DBG("output status: %d", caps->status);
303 TDM_DBG("output type : %d", caps->type);
304 for (i = 0; i < caps->prop_count; i++)
305 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
306 for (i = 0; i < caps->mode_count; i++) {
307 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
308 caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
309 caps->modes[i].flags, caps->modes[i].type);
310 TDM_DBG("\t\t %d, %d, %d, %d, %d",
311 caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
312 caps->modes[i].htotal, caps->modes[i].hskew);
313 TDM_DBG("\t\t %d, %d, %d, %d, %d",
314 caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
315 caps->modes[i].vtotal, caps->modes[i].vscan);
317 TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h);
318 TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h);
319 TDM_DBG("output align: %d", caps->preferred_align);
321 return TDM_ERROR_NONE;
325 _tdm_display_update_layer(tdm_private_display *private_display,
326 tdm_private_output *private_output,
327 tdm_layer *layer_backend)
329 tdm_private_layer *private_layer;
332 private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
333 if (!private_layer) {
334 private_layer = calloc(1, sizeof(tdm_private_layer));
335 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
337 LIST_ADD(&private_layer->link, &private_output->layer_list);
338 private_layer->private_display = private_display;
339 private_layer->private_output = private_output;
340 private_layer->layer_backend = layer_backend;
342 LIST_INITHEAD(&private_layer->capture_list);
344 private_layer->usable = 1;
346 _tdm_display_destroy_caps_layer(&private_layer->caps);
348 ret = _tdm_display_update_caps_layer(private_display, layer_backend,
349 &private_layer->caps);
350 if (ret != TDM_ERROR_NONE)
353 return TDM_ERROR_NONE;
355 _tdm_display_destroy_private_layer(private_layer);
360 _tdm_display_update_output(tdm_private_display *private_display,
361 tdm_output *output_backend, int pipe)
363 tdm_func_output *func_output = &private_display->func_output;
364 tdm_private_output *private_output = NULL;
365 tdm_layer **layers = NULL;
366 int layer_count = 0, i;
369 private_output = _tdm_display_find_private_output(private_display,
371 if (!private_output) {
372 private_output = calloc(1, sizeof(tdm_private_output));
373 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
375 LIST_ADD(&private_output->link, &private_display->output_list);
376 private_output->private_display = private_display;
377 private_output->output_backend = output_backend;
378 private_output->pipe = pipe;
380 LIST_INITHEAD(&private_output->layer_list);
381 LIST_INITHEAD(&private_output->capture_list);
382 LIST_INITHEAD(&private_output->vblank_handler_list);
383 LIST_INITHEAD(&private_output->commit_handler_list);
385 _tdm_display_destroy_caps_output(&private_output->caps);
387 ret = _tdm_display_update_caps_output(private_display, output_backend,
388 &private_output->caps);
389 if (ret != TDM_ERROR_NONE)
392 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
393 if (ret != TDM_ERROR_NONE)
396 for (i = 0; i < layer_count; i++) {
397 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
398 if (ret != TDM_ERROR_NONE)
404 return TDM_ERROR_NONE;
406 _tdm_display_destroy_private_output(private_output);
412 _tdm_display_update_internal(tdm_private_display *private_display,
415 tdm_func_display *func_display = &private_display->func_display;
416 tdm_output **outputs = NULL;
417 int output_count = 0, i;
420 LIST_INITHEAD(&private_display->output_list);
421 LIST_INITHEAD(&private_display->pp_list);
424 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
425 if (ret != TDM_ERROR_NONE)
428 ret = _tdm_display_update_caps_capture(private_display,
429 &private_display->caps_capture);
430 if (ret != TDM_ERROR_NONE)
434 outputs = func_display->display_get_outputs(private_display->bdata,
435 &output_count, &ret);
436 if (ret != TDM_ERROR_NONE)
439 for (i = 0; i < output_count; i++) {
440 ret = _tdm_display_update_output(private_display, outputs[i], i);
441 if (ret != TDM_ERROR_NONE)
447 return TDM_ERROR_NONE;
450 _tdm_display_destroy_private_display(private_display);
456 tdm_display_update(tdm_display *dpy)
458 tdm_private_display *private_display;
461 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
463 private_display = dpy;
464 _pthread_mutex_lock(&private_display->lock);
466 ret = _tdm_display_update_internal(private_display, 1);
468 _pthread_mutex_unlock(&private_display->lock);
473 #define SUFFIX_MODULE ".so"
474 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
477 int tdm_debug_buffer;
480 static tdm_private_display *g_private_display;
481 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
484 _tdm_display_check_module(tdm_backend_module *module)
491 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
492 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
494 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
496 name = module->name ? module->name : "unknown";
497 vendor = module->vendor ? module->vendor : "unknown";
498 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
499 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
501 TDM_INFO("TDM module name: %s", name);
502 TDM_INFO("'%s' vendor: %s", name, vendor);
503 TDM_INFO("'%s' version: %d.%d", name, major, minor);
505 if (major != abimaj) {
506 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
507 return TDM_ERROR_BAD_MODULE;
510 if (minor > abimin) {
511 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
512 return TDM_ERROR_BAD_MODULE;
516 TDM_ERR("'%s' doesn't have init function", name);
517 return TDM_ERROR_BAD_MODULE;
520 if (!module->deinit) {
521 TDM_ERR("'%s' doesn't have deinit function", name);
522 return TDM_ERROR_BAD_MODULE;
525 return TDM_ERROR_NONE;
529 _tdm_display_check_backend_functions(tdm_private_display *private_display)
531 tdm_func_display *func_display = &private_display->func_display;
532 tdm_func_output *func_output = &private_display->func_output;
533 tdm_func_layer *func_layer = &private_display->func_layer;
536 /* below functions should be implemented in backend side */
538 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
539 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
540 TDM_ERROR_BAD_MODULE);
541 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
542 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
543 TDM_ERROR_BAD_MODULE);
544 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
545 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
547 ret = func_display->display_get_capabilitiy(private_display->bdata,
548 &private_display->caps_display);
549 if (ret != TDM_ERROR_NONE) {
550 TDM_ERR("display_get_capabilitiy() failed");
551 return TDM_ERROR_BAD_MODULE;
554 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
555 tdm_func_pp *func_pp = &private_display->func_pp;
556 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
557 TDM_ERROR_BAD_MODULE);
558 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
559 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
560 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
561 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
564 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
565 tdm_func_capture *func_capture = &private_display->func_capture;
566 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
567 TDM_ERROR_BAD_MODULE);
568 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
569 TDM_ERROR_BAD_MODULE);
570 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
571 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
572 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
573 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
574 TDM_ERROR_BAD_MODULE);
577 return TDM_ERROR_NONE;
581 _tdm_display_load_module_with_file(tdm_private_display *private_display,
584 char path[PATH_MAX] = {0,};
585 tdm_backend_module *module_data;
589 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
591 TDM_TRACE_BEGIN(Load_Backend);
593 module = dlopen(path, RTLD_LAZY);
595 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
597 return TDM_ERROR_BAD_MODULE;
600 module_data = dlsym(module, "tdm_backend_module_data");
602 TDM_ERR("'%s' doesn't have data object", file);
603 ret = TDM_ERROR_BAD_MODULE;
608 private_display->module_data = module_data;
609 private_display->module = module;
611 /* check if version, init() and deinit() are valid or not */
612 ret = _tdm_display_check_module(module_data);
613 if (ret != TDM_ERROR_NONE)
618 /* We don't care if backend_data is NULL or not. It's up to backend. */
619 TDM_TRACE_BEGIN(Init_Backend);
620 private_display->bdata = module_data->init((tdm_display *)private_display,
623 if (ret != TDM_ERROR_NONE) {
624 TDM_ERR("'%s' init failed", file);
628 ret = _tdm_display_check_backend_functions(private_display);
629 if (ret != TDM_ERROR_NONE) {
630 module_data->deinit(private_display->bdata);
631 private_display->bdata = NULL;
635 TDM_INFO("Success to load module(%s)", file);
637 return TDM_ERROR_NONE;
640 private_display->module_data = NULL;
641 private_display->module = NULL;
646 _tdm_display_load_module(tdm_private_display *private_display)
648 const char *module_name;
649 struct dirent **namelist;
653 module_name = getenv("TDM_MODULE");
655 module_name = DEFAULT_MODULE;
657 /* load bufmgr priv from default lib */
658 ret = _tdm_display_load_module_with_file(private_display, module_name);
659 if (ret == TDM_ERROR_NONE)
660 return TDM_ERROR_NONE;
662 /* load bufmgr priv from configured path */
663 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
665 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
666 return TDM_ERROR_BAD_MODULE;
669 ret = TDM_ERROR_BAD_MODULE;
671 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
672 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
682 _tdm_display_unload_module(tdm_private_display *private_display)
684 if (private_display->module_data)
685 private_display->module_data->deinit(private_display->bdata);
686 if (private_display->module)
687 dlclose(private_display->module);
689 private_display->bdata = NULL;
690 private_display->module_data = NULL;
691 private_display->module = NULL;
695 tdm_display_init(tdm_error *error)
697 tdm_private_display *private_display = NULL;
701 _pthread_mutex_lock(&gLock);
703 if (g_private_display) {
704 g_private_display->init_count++;
705 _pthread_mutex_unlock(&gLock);
707 *error = TDM_ERROR_NONE;
708 return g_private_display;
711 debug = getenv("TDM_DEBUG");
712 if (debug && (strstr(debug, "1")))
715 debug = getenv("TDM_DEBUG_BUFFER");
716 if (debug && (strstr(debug, "1")))
717 tdm_debug_buffer = 1;
719 debug = getenv("TDM_DEBUG_MUTEX");
720 if (debug && (strstr(debug, "1")))
723 private_display = calloc(1, sizeof(tdm_private_display));
724 if (!private_display) {
725 ret = TDM_ERROR_OUT_OF_MEMORY;
726 TDM_ERR("'private_display != NULL' failed");
730 if (pthread_mutex_init(&private_display->lock, NULL)) {
731 ret = TDM_ERROR_OPERATION_FAILED;
732 TDM_ERR("mutex init failed: %m");
733 goto failed_mutex_init;
736 ret = tdm_event_init(private_display);
737 if (ret != TDM_ERROR_NONE)
740 ret = _tdm_display_load_module(private_display);
741 if (ret != TDM_ERROR_NONE)
744 TDM_TRACE_BEGIN(Update_Display);
745 ret = _tdm_display_update_internal(private_display, 0);
747 if (ret != TDM_ERROR_NONE)
750 tdm_event_create_main_source(private_display);
752 private_display->init_count = 1;
754 g_private_display = private_display;
757 *error = TDM_ERROR_NONE;
759 _pthread_mutex_unlock(&gLock);
761 return (tdm_display *)private_display;
764 _tdm_display_unload_module(private_display);
766 pthread_mutex_destroy(&private_display->lock);
768 free(private_display);
771 tdm_debug_buffer = 0;
774 _pthread_mutex_unlock(&gLock);
779 tdm_display_deinit(tdm_display *dpy)
781 tdm_private_display *private_display = dpy;
783 if (!private_display)
786 _pthread_mutex_lock(&gLock);
788 private_display->init_count--;
789 if (private_display->init_count > 0) {
790 _pthread_mutex_unlock(&gLock);
794 _pthread_mutex_lock(&private_display->lock);
796 _tdm_display_destroy_private_display(private_display);
797 _tdm_display_unload_module(private_display);
798 tdm_event_deinit(private_display);
800 tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
802 _pthread_mutex_unlock(&private_display->lock);
804 pthread_mutex_destroy(&private_display->lock);
805 free(private_display);
806 g_private_display = NULL;
808 tdm_debug_buffer = 0;
810 _pthread_mutex_unlock(&gLock);