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"
44 static tdm_private_layer*
45 _tdm_display_find_private_layer(tdm_private_output *private_output, tdm_layer *layer_backend)
47 tdm_private_layer *private_layer = NULL;
49 LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
51 if (private_layer->layer_backend == layer_backend)
58 static tdm_private_output*
59 _tdm_display_find_private_output(tdm_private_display *private_display, tdm_output *output_backend)
61 tdm_private_output *private_output = NULL;
63 LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link)
65 if (private_output->output_backend == output_backend)
66 return private_output;
73 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
75 free(caps_pp->formats);
76 memset(caps_pp, 0, sizeof(tdm_caps_pp));
80 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
82 free(caps_capture->formats);
83 memset(caps_capture, 0, sizeof(tdm_caps_capture));
87 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
89 free(caps_layer->formats);
90 free(caps_layer->props);
91 memset(caps_layer, 0, sizeof(tdm_caps_layer));
95 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
97 free(caps_output->modes);
98 free(caps_output->props);
99 memset(caps_output, 0, sizeof(tdm_caps_output));
103 _tdm_display_destroy_private_layer(tdm_private_layer *private_layer)
105 tdm_private_capture *c = NULL, *cc = NULL;
107 LIST_DEL(&private_layer->link);
109 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link)
110 tdm_capture_destroy_internal(c);
112 _tdm_display_destroy_caps_layer(&private_layer->caps);
118 _tdm_display_destroy_private_output(tdm_private_output *private_output)
120 tdm_private_layer *l = NULL, *ll = NULL;
121 tdm_private_capture *c = NULL, *cc = NULL;
122 tdm_private_vblank_handler *v = NULL, *vv = NULL;
123 tdm_private_commit_handler *m = NULL, *mm = NULL;
125 LIST_DEL(&private_output->link);
127 free(private_output->layers_ptr);
129 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)
141 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
142 tdm_capture_destroy_internal(c);
144 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
145 _tdm_display_destroy_private_layer(l);
147 _tdm_display_destroy_caps_output(&private_output->caps);
149 free(private_output);
153 _tdm_display_destroy_private_display(tdm_private_display *private_display)
155 tdm_private_output *o = NULL, *oo = NULL;
156 tdm_private_pp *p = NULL, *pp = NULL;
158 free(private_display->outputs_ptr);
160 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
161 tdm_pp_destroy_internal(p);
163 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
164 _tdm_display_destroy_private_output(o);
166 _tdm_display_destroy_caps_pp(&private_display->caps_pp);
167 _tdm_display_destroy_caps_capture(&private_display->caps_capture);
169 private_display->capabilities = 0;
170 private_display->caps_display.max_layer_count = -1;
174 _tdm_display_update_caps_pp(tdm_private_display *private_display, tdm_caps_pp *caps)
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)
189 TDM_ERR("no display_get_pp_capability()");
190 return TDM_ERROR_BAD_MODULE;
193 ret = func_display->display_get_pp_capability(private_display->bdata, caps);
194 if (ret != TDM_ERROR_NONE)
196 TDM_ERR("display_get_pp_capability() failed");
197 return TDM_ERROR_BAD_MODULE;
200 TDM_DBG("pp capabilities: %x", caps->capabilities);
202 for (i = 0; i < caps->format_count; i++)
203 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
204 TDM_DBG("pp formats: %s", buf);
205 TDM_DBG("pp min : %dx%d", caps->min_w, caps->min_h);
206 TDM_DBG("pp max : %dx%d", caps->max_w, caps->max_h);
207 TDM_DBG("pp align: %d", caps->preferred_align);
209 return TDM_ERROR_NONE;
213 _tdm_display_update_caps_capture(tdm_private_display *private_display, tdm_caps_capture *caps)
215 tdm_func_display *func_display = &private_display->func_display;
217 int bufsize = sizeof(buf);
219 int *len_buf = &bufsize;
223 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
224 return TDM_ERROR_NONE;
226 if (!func_display->display_get_capture_capability)
228 TDM_ERR("no display_get_capture_capability()");
229 return TDM_ERROR_BAD_MODULE;
232 ret = func_display->display_get_capture_capability(private_display->bdata, caps);
233 if (ret != TDM_ERROR_NONE)
235 TDM_ERR("display_get_capture_capability() failed");
236 return TDM_ERROR_BAD_MODULE;
240 for (i = 0; i < caps->format_count; i++)
241 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
242 TDM_DBG("capture formats: %s", buf);
244 return TDM_ERROR_NONE;
248 _tdm_display_update_caps_layer(tdm_private_display *private_display,
249 tdm_layer *layer_backend, tdm_caps_layer *caps)
251 tdm_func_layer *func_layer = &private_display->func_layer;
253 int bufsize = sizeof(buf);
255 int *len_buf = &bufsize;
259 if (!func_layer->layer_get_capability)
261 TDM_ERR("no layer_get_capability()");
262 return TDM_ERROR_BAD_MODULE;
265 ret = func_layer->layer_get_capability(layer_backend, caps);
266 if (ret != TDM_ERROR_NONE)
268 TDM_ERR("layer_get_capability() failed");
269 return TDM_ERROR_BAD_MODULE;
272 TDM_DBG("layer capabilities: %x", caps->capabilities);
273 TDM_DBG("layer zpos : %d", caps->zpos);
275 for (i = 0; i < caps->format_count; i++)
276 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
277 TDM_DBG("layer formats: %s", buf);
278 for (i = 0; i < caps->prop_count; i++)
279 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
281 return TDM_ERROR_NONE;
285 _tdm_display_update_caps_output(tdm_private_display *private_display,
286 tdm_output *output_backend, tdm_caps_output *caps)
288 tdm_func_output *func_output = &private_display->func_output;
292 if (!func_output->output_get_capability)
294 TDM_ERR("no output_get_capability()");
295 return TDM_ERROR_BAD_MODULE;
298 ret = func_output->output_get_capability(output_backend, caps);
299 if (ret != TDM_ERROR_NONE)
301 TDM_ERR("output_get_capability() failed");
302 return TDM_ERROR_BAD_MODULE;
305 TDM_DBG("output maker: %s", caps->maker);
306 TDM_DBG("output model: %s", caps->model);
307 TDM_DBG("output name: %s", caps->name);
308 TDM_DBG("output status: %d", caps->status);
309 TDM_DBG("output type : %d", caps->type);
310 for (i = 0; i < caps->prop_count; i++)
311 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
312 for (i = 0; i < caps->mode_count; i++)
314 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
315 caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
316 caps->modes[i].flags, caps->modes[i].type);
317 TDM_DBG("\t\t %d, %d, %d, %d, %d",
318 caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
319 caps->modes[i].htotal, caps->modes[i].hskew);
320 TDM_DBG("\t\t %d, %d, %d, %d, %d",
321 caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
322 caps->modes[i].vtotal, caps->modes[i].vscan);
324 TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h);
325 TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h);
326 TDM_DBG("output align: %d", caps->preferred_align);
328 return TDM_ERROR_NONE;
332 _tdm_display_update_layer(tdm_private_display *private_display,
333 tdm_private_output *private_output,
334 tdm_layer *layer_backend)
336 tdm_private_layer *private_layer;
339 private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
342 private_layer = calloc(1, sizeof(tdm_private_layer));
343 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
345 LIST_ADD(&private_layer->link, &private_output->layer_list);
346 private_layer->private_display = private_display;
347 private_layer->private_output = private_output;
348 private_layer->layer_backend = layer_backend;
350 LIST_INITHEAD(&private_layer->capture_list);
352 private_layer->usable = 1;
355 _tdm_display_destroy_caps_layer(&private_layer->caps);
357 ret = _tdm_display_update_caps_layer(private_display, layer_backend, &private_layer->caps);
358 if (ret != TDM_ERROR_NONE)
361 return TDM_ERROR_NONE;
363 _tdm_display_destroy_private_layer(private_layer);
368 _tdm_display_update_output(tdm_private_display *private_display,
369 tdm_output *output_backend, int pipe)
371 tdm_func_output *func_output = &private_display->func_output;
372 tdm_private_output *private_output = NULL;
373 tdm_layer **layers = NULL;
374 int layer_count = 0, i;
377 private_output = _tdm_display_find_private_output(private_display, output_backend);
380 private_output = calloc(1, sizeof(tdm_private_output));
381 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
383 LIST_ADD(&private_output->link, &private_display->output_list);
384 private_output->private_display = private_display;
385 private_output->output_backend = output_backend;
386 private_output->pipe = pipe;
388 LIST_INITHEAD(&private_output->layer_list);
389 LIST_INITHEAD(&private_output->capture_list);
390 LIST_INITHEAD(&private_output->vblank_handler_list);
391 LIST_INITHEAD(&private_output->commit_handler_list);
394 _tdm_display_destroy_caps_output(&private_output->caps);
396 ret = _tdm_display_update_caps_output(private_display, output_backend, &private_output->caps);
397 if (ret != TDM_ERROR_NONE)
400 layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
401 if (ret != TDM_ERROR_NONE)
404 for (i = 0; i < layer_count; i++)
406 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
407 if (ret != TDM_ERROR_NONE)
413 return TDM_ERROR_NONE;
415 _tdm_display_destroy_private_output(private_output);
421 _tdm_display_update_internal(tdm_private_display *private_display, int only_display)
423 tdm_func_display *func_display = &private_display->func_display;
424 tdm_output **outputs = NULL;
425 int output_count = 0, i;
428 LIST_INITHEAD(&private_display->output_list);
429 LIST_INITHEAD(&private_display->pp_list);
433 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
434 if (ret != TDM_ERROR_NONE)
437 ret = _tdm_display_update_caps_capture(private_display, &private_display->caps_capture);
438 if (ret != TDM_ERROR_NONE)
442 outputs = func_display->display_get_outputs(private_display->bdata, &output_count, &ret);
443 if (ret != TDM_ERROR_NONE)
446 for (i = 0; i < output_count; i++)
448 ret = _tdm_display_update_output(private_display, outputs[i], i);
449 if (ret != TDM_ERROR_NONE)
455 return TDM_ERROR_NONE;
458 _tdm_display_destroy_private_display(private_display);
464 _tdm_display_init_bufmgr(tdm_private_display *private_display)
466 tdm_func_display *func_display = &private_display->func_display;
470 if (func_display->display_get_buffer_fd)
472 ret = func_display->display_get_buffer_fd(private_display->bdata, &buffer_fd);
473 if (ret != TDM_ERROR_NONE)
475 TDM_ERR("failed to get buffer fd");
480 private_display->bufmgr = tbm_bufmgr_init(buffer_fd);
481 if (!private_display->bufmgr)
483 TDM_ERR("failed to init TBM bufmgr: fd(%d)", buffer_fd);
484 return TDM_ERROR_OUT_OF_MEMORY;
487 TDM_INFO("init TBM bufmgr: fd(%d)", buffer_fd);
489 return TDM_ERROR_NONE;
494 tdm_display_update(tdm_display *dpy)
496 tdm_private_display *private_display;
499 TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
501 private_display = dpy;
502 pthread_mutex_lock(&private_display->lock);
504 ret = _tdm_display_update_internal(private_display, 1);
506 pthread_mutex_unlock(&private_display->lock);
511 #define SUFFIX_MODULE ".so"
512 #define DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE
516 static tdm_private_display *g_private_display;
517 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
520 _tdm_display_check_module(tdm_backend_module *module)
527 abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
528 abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
530 TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
532 name = module->name ? module->name : "unknown";
533 vendor = module->vendor ? module->vendor : "unknown";
534 major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
535 minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
537 TDM_INFO("TDM module name: %s", name);
538 TDM_INFO("'%s' vendor: %s", name, vendor);
539 TDM_INFO("'%s' version: %d.%d", name, major, minor);
543 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
544 return TDM_ERROR_BAD_MODULE;
549 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
550 return TDM_ERROR_BAD_MODULE;
555 TDM_ERR("'%s' doesn't have init function", name);
556 return TDM_ERROR_BAD_MODULE;
561 TDM_ERR("'%s' doesn't have deinit function", name);
562 return TDM_ERROR_BAD_MODULE;
565 return TDM_ERROR_NONE;
569 _tdm_display_check_backend_functions(tdm_private_display *private_display)
571 tdm_func_display *func_display = &private_display->func_display;
572 tdm_func_output *func_output = &private_display->func_output;
573 tdm_func_layer *func_layer = &private_display->func_layer;
576 /* below functions should be implemented in backend side */
578 TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
579 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy, TDM_ERROR_BAD_MODULE);
580 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
581 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability, TDM_ERROR_BAD_MODULE);
582 TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
583 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
585 ret = func_display->display_get_capabilitiy(private_display->bdata,
586 &private_display->caps_display);
587 if (ret != TDM_ERROR_NONE)
589 TDM_ERR("display_get_capabilitiy() failed");
590 return TDM_ERROR_BAD_MODULE;
593 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)
595 tdm_func_pp *func_pp = &private_display->func_pp;
596 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability, TDM_ERROR_BAD_MODULE);
597 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
598 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
599 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
600 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
603 if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)
605 tdm_func_capture *func_capture = &private_display->func_capture;
606 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability, TDM_ERROR_BAD_MODULE);
607 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture, TDM_ERROR_BAD_MODULE);
608 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
609 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
610 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
611 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler, TDM_ERROR_BAD_MODULE);
614 return TDM_ERROR_NONE;
618 _tdm_display_load_module_with_file(tdm_private_display *private_display, const char *file)
620 char path[PATH_MAX] = {0,};
621 tdm_backend_module *module_data;
625 snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
627 module = dlopen(path, RTLD_LAZY);
630 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
631 return TDM_ERROR_BAD_MODULE;
634 module_data = dlsym(module, "tdm_backend_module_data");
637 TDM_ERR("'%s' doesn't have data object", file);
638 ret = TDM_ERROR_BAD_MODULE;
642 private_display->module_data = module_data;
643 private_display->module = module;
645 /* check if version, init() and deinit() are valid or not */
646 ret = _tdm_display_check_module(module_data);
647 if (ret != TDM_ERROR_NONE)
650 /* We don't care if backend_data is NULL or not. It's up to backend. */
651 private_display->bdata = module_data->init((tdm_display*)private_display, &ret);
652 if (ret != TDM_ERROR_NONE)
654 TDM_ERR("'%s' init failed", file);
658 ret = _tdm_display_check_backend_functions(private_display);
659 if (ret != TDM_ERROR_NONE)
661 module_data->deinit(private_display->bdata);
662 private_display->bdata = NULL;
666 TDM_INFO("Success to load module(%s)", file);
668 return TDM_ERROR_NONE;
671 private_display->module_data = NULL;
672 private_display->module = NULL;
677 _tdm_display_load_module(tdm_private_display *private_display)
679 const char *module_name;
680 struct dirent **namelist;
684 module_name = getenv("TDM_MODULE");
686 module_name = DEFAULT_MODULE;
688 /* load bufmgr priv from default lib */
689 ret = _tdm_display_load_module_with_file(private_display, module_name);
690 if (ret == TDM_ERROR_NONE)
691 return TDM_ERROR_NONE;
693 /* load bufmgr priv from configured path */
694 n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
697 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
698 return TDM_ERROR_BAD_MODULE;
701 ret = TDM_ERROR_BAD_MODULE;
704 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
705 ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
715 _tdm_display_unload_module(tdm_private_display *private_display)
717 if (private_display->module_data)
718 private_display->module_data->deinit(private_display->bdata);
719 if (private_display->module)
720 dlclose(private_display->module);
722 private_display->bdata = NULL;
723 private_display->module_data = NULL;
724 private_display->module = NULL;
728 tdm_display_init(tdm_error *error)
730 tdm_private_display *private_display = NULL;
734 pthread_mutex_lock(&gLock);
736 if (g_private_display)
738 g_private_display->init_count++;
739 pthread_mutex_unlock(&gLock);
741 *error = TDM_ERROR_NONE;
742 return g_private_display;
745 debug = getenv("TDM_DEBUG");
746 if (debug && (strstr(debug, "1")))
749 private_display = calloc(1, sizeof(tdm_private_display));
750 if (!private_display)
752 ret = TDM_ERROR_OUT_OF_MEMORY;
753 TDM_ERR("'private_display != NULL' failed");
757 if (pthread_mutex_init(&private_display->lock, NULL))
759 ret = TDM_ERROR_OPERATION_FAILED;
760 TDM_ERR("mutex init failed: %m");
761 goto failed_mutex_init;
764 ret = _tdm_display_load_module(private_display);
765 if (ret != TDM_ERROR_NONE)
768 ret = _tdm_display_update_internal(private_display, 0);
769 if (ret != TDM_ERROR_NONE)
772 ret = _tdm_display_init_bufmgr(private_display);
773 if (ret != TDM_ERROR_NONE)
776 private_display->init_count = 1;
778 g_private_display = private_display;
781 *error = TDM_ERROR_NONE;
783 pthread_mutex_unlock(&gLock);
785 return (tdm_display*)private_display;
788 _tdm_display_unload_module(private_display);
790 pthread_mutex_destroy(&private_display->lock);
792 free(private_display);
797 pthread_mutex_unlock(&gLock);
802 tdm_display_deinit(tdm_display *dpy)
804 tdm_private_display *private_display = dpy;
806 if (!private_display)
809 pthread_mutex_lock(&gLock);
811 private_display->init_count--;
812 if (private_display->init_count > 0)
814 pthread_mutex_unlock(&gLock);
818 pthread_mutex_lock(&private_display->lock);
820 if (private_display->bufmgr)
821 tbm_bufmgr_deinit(private_display->bufmgr);
823 _tdm_display_destroy_private_display(private_display);
824 _tdm_display_unload_module(private_display);
826 pthread_mutex_unlock(&private_display->lock);
828 pthread_mutex_destroy(&private_display->lock);
829 free(private_display);
832 pthread_mutex_unlock(&gLock);