rename tdm_event to tdm_event_loop
[platform/core/uifw/libtdm.git] / src / tdm.c
1 /**************************************************************************
2
3 libtdm
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
13
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:
21
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
24 of the Software.
25
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.
33
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm.h"
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43 #include "tdm_helper.h"
44
45 static tdm_private_layer *
46 _tdm_display_find_private_layer(tdm_private_output *private_output,
47                                 tdm_layer *layer_backend)
48 {
49         tdm_private_layer *private_layer = NULL;
50
51         LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
52                 if (private_layer->layer_backend == layer_backend)
53                         return private_layer;
54         }
55
56         return NULL;
57 }
58
59 static tdm_private_output *
60 _tdm_display_find_private_output(tdm_private_display *private_display,
61                                  tdm_output *output_backend)
62 {
63         tdm_private_output *private_output = NULL;
64
65         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
66                 if (private_output->output_backend == output_backend)
67                         return private_output;
68         }
69
70         return NULL;
71 }
72
73 INTERN tdm_private_output *
74 tdm_display_find_output_stamp(tdm_private_display *private_display,
75                               unsigned long stamp)
76 {
77         tdm_private_output *private_output = NULL;
78
79         LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
80                 if (private_output->stamp == stamp)
81                         return private_output;
82         }
83
84         return NULL;
85 }
86
87 static void
88 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
89 {
90         free(caps_pp->formats);
91         memset(caps_pp, 0, sizeof(tdm_caps_pp));
92 }
93
94 static void
95 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
96 {
97         free(caps_capture->formats);
98         memset(caps_capture, 0, sizeof(tdm_caps_capture));
99 }
100
101 static void
102 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
103 {
104         free(caps_layer->formats);
105         free(caps_layer->props);
106         memset(caps_layer, 0, sizeof(tdm_caps_layer));
107 }
108
109 static void
110 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
111 {
112         free(caps_output->modes);
113         free(caps_output->props);
114         memset(caps_output, 0, sizeof(tdm_caps_output));
115 }
116
117 static void
118 _tdm_display_destroy_private_layer(tdm_private_layer *private_layer)
119 {
120         tdm_private_capture *c = NULL, *cc = NULL;
121
122         LIST_DEL(&private_layer->link);
123
124         LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link)
125         tdm_capture_destroy_internal(c);
126
127         _tdm_display_destroy_caps_layer(&private_layer->caps);
128
129         free(private_layer);
130 }
131
132 static void
133 _tdm_display_destroy_private_output(tdm_private_output *private_output)
134 {
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;
140
141         LIST_DEL(&private_output->link);
142
143         free(private_output->layers_ptr);
144
145         LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) {
146                 LIST_DEL(&v->link);
147                 free(v);
148         }
149
150         LIST_FOR_EACH_ENTRY_SAFE(m, mm, &private_output->commit_handler_list, link) {
151                 LIST_DEL(&m->link);
152                 free(m);
153         }
154
155         LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
156                 LIST_DEL(&h->link);
157                 free(h);
158         }
159
160         LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
161         tdm_capture_destroy_internal(c);
162
163         LIST_FOR_EACH_ENTRY_SAFE(l, ll, &private_output->layer_list, link)
164         _tdm_display_destroy_private_layer(l);
165
166         _tdm_display_destroy_caps_output(&private_output->caps);
167
168         private_output->stamp = 0;
169         free(private_output);
170 }
171
172 static void
173 _tdm_display_destroy_private_display(tdm_private_display *private_display)
174 {
175         tdm_private_output *o = NULL, *oo = NULL;
176         tdm_private_pp *p = NULL, *pp = NULL;
177
178         free(private_display->outputs_ptr);
179
180         LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link)
181         tdm_pp_destroy_internal(p);
182
183         LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link)
184         _tdm_display_destroy_private_output(o);
185
186         _tdm_display_destroy_caps_pp(&private_display->caps_pp);
187         _tdm_display_destroy_caps_capture(&private_display->caps_capture);
188
189         private_display->capabilities = 0;
190         private_display->caps_display.max_layer_count = -1;
191 }
192
193 static tdm_error
194 _tdm_display_update_caps_pp(tdm_private_display *private_display,
195                             tdm_caps_pp *caps)
196 {
197         tdm_func_display *func_display = &private_display->func_display;
198         char buf[1024];
199         int bufsize = sizeof(buf);
200         char *str_buf = buf;
201         int *len_buf = &bufsize;
202         int i;
203         tdm_error ret;
204
205         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP))
206                 return TDM_ERROR_NONE;
207
208         if (!func_display->display_get_pp_capability) {
209                 TDM_ERR("no display_get_pp_capability()");
210                 return TDM_ERROR_BAD_MODULE;
211         }
212
213         ret = func_display->display_get_pp_capability(private_display->bdata, caps);
214         if (ret != TDM_ERROR_NONE) {
215                 TDM_ERR("display_get_pp_capability() failed");
216                 return TDM_ERROR_BAD_MODULE;
217         }
218
219         TDM_DBG("pp capabilities: %x", caps->capabilities);
220         buf[0] = '\0';
221         for (i = 0; i < caps->format_count; i++)
222                 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
223         TDM_DBG("pp formats: %s", buf);
224         TDM_DBG("pp min  : %dx%d", caps->min_w, caps->min_h);
225         TDM_DBG("pp max  : %dx%d", caps->max_w, caps->max_h);
226         TDM_DBG("pp align: %d", caps->preferred_align);
227
228         return TDM_ERROR_NONE;
229 }
230
231 static tdm_error
232 _tdm_display_update_caps_capture(tdm_private_display *private_display,
233                                  tdm_caps_capture *caps)
234 {
235         tdm_func_display *func_display = &private_display->func_display;
236         char buf[1024];
237         int bufsize = sizeof(buf);
238         char *str_buf = buf;
239         int *len_buf = &bufsize;
240         int i;
241         tdm_error ret;
242
243         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE))
244                 return TDM_ERROR_NONE;
245
246         if (!func_display->display_get_capture_capability) {
247                 TDM_ERR("no display_get_capture_capability()");
248                 return TDM_ERROR_BAD_MODULE;
249         }
250
251         ret = func_display->display_get_capture_capability(private_display->bdata,
252                         caps);
253         if (ret != TDM_ERROR_NONE) {
254                 TDM_ERR("display_get_capture_capability() failed");
255                 return TDM_ERROR_BAD_MODULE;
256         }
257
258         buf[0] = '\0';
259         for (i = 0; i < caps->format_count; i++)
260                 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
261         TDM_DBG("capture formats: %s", buf);
262
263         return TDM_ERROR_NONE;
264 }
265
266 static tdm_error
267 _tdm_display_update_caps_layer(tdm_private_display *private_display,
268                                tdm_layer *layer_backend, tdm_caps_layer *caps)
269 {
270         tdm_func_layer *func_layer = &private_display->func_layer;
271         char buf[1024];
272         int bufsize = sizeof(buf);
273         char *str_buf = buf;
274         int *len_buf = &bufsize;
275         int i;
276         tdm_error ret;
277
278         if (!func_layer->layer_get_capability) {
279                 TDM_ERR("no layer_get_capability()");
280                 return TDM_ERROR_BAD_MODULE;
281         }
282
283         ret = func_layer->layer_get_capability(layer_backend, caps);
284         if (ret != TDM_ERROR_NONE) {
285                 TDM_ERR("layer_get_capability() failed");
286                 return TDM_ERROR_BAD_MODULE;
287         }
288
289         TDM_DBG("layer capabilities: %x", caps->capabilities);
290         TDM_DBG("layer zpos : %d", caps->zpos);
291         buf[0] = '\0';
292         for (i = 0; i < caps->format_count; i++)
293                 TDM_SNPRINTF(str_buf, len_buf, "%c%c%c%c ", FOURCC_STR(caps->formats[i]));
294         TDM_DBG("layer formats: %s", buf);
295         for (i = 0; i < caps->prop_count; i++)
296                 TDM_DBG("layer props: %d, %s", caps->props[i].id, caps->props[i].name);
297
298         return TDM_ERROR_NONE;
299 }
300
301 static tdm_error
302 _tdm_display_update_caps_output(tdm_private_display *private_display,
303                                 tdm_output *output_backend, tdm_caps_output *caps)
304 {
305         tdm_func_output *func_output = &private_display->func_output;
306         int i;
307         tdm_error ret;
308
309         if (!func_output->output_get_capability) {
310                 TDM_ERR("no output_get_capability()");
311                 return TDM_ERROR_BAD_MODULE;
312         }
313
314         ret = func_output->output_get_capability(output_backend, caps);
315         if (ret != TDM_ERROR_NONE) {
316                 TDM_ERR("output_get_capability() failed");
317                 return TDM_ERROR_BAD_MODULE;
318         }
319
320         TDM_DBG("output maker: %s", caps->maker);
321         TDM_DBG("output model: %s", caps->model);
322         TDM_DBG("output name: %s", caps->name);
323         TDM_DBG("output status: %d", caps->status);
324         TDM_DBG("output type : %d", caps->type);
325         for (i = 0; i < caps->prop_count; i++)
326                 TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name);
327         for (i = 0; i < caps->mode_count; i++) {
328                 TDM_DBG("output modes: name(%s), clock(%d) vrefresh(%d), flags(%x), type(%d)",
329                         caps->modes[i].name, caps->modes[i].clock, caps->modes[i].vrefresh,
330                         caps->modes[i].flags, caps->modes[i].type);
331                 TDM_DBG("\t\t %d, %d, %d, %d, %d",
332                         caps->modes[i].hdisplay, caps->modes[i].hsync_start, caps->modes[i].hsync_end,
333                         caps->modes[i].htotal, caps->modes[i].hskew);
334                 TDM_DBG("\t\t %d, %d, %d, %d, %d",
335                         caps->modes[i].vdisplay, caps->modes[i].vsync_start, caps->modes[i].vsync_end,
336                         caps->modes[i].vtotal, caps->modes[i].vscan);
337         }
338         TDM_DBG("output min  : %dx%d", caps->min_w, caps->min_h);
339         TDM_DBG("output max  : %dx%d", caps->max_w, caps->max_h);
340         TDM_DBG("output align: %d", caps->preferred_align);
341
342         return TDM_ERROR_NONE;
343 }
344
345 static tdm_error
346 _tdm_display_update_layer(tdm_private_display *private_display,
347                           tdm_private_output *private_output,
348                           tdm_layer *layer_backend)
349 {
350         tdm_private_layer *private_layer;
351         tdm_error ret;
352
353         private_layer = _tdm_display_find_private_layer(private_output, layer_backend);
354         if (!private_layer) {
355                 private_layer = calloc(1, sizeof(tdm_private_layer));
356                 TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY);
357
358                 LIST_ADD(&private_layer->link, &private_output->layer_list);
359                 private_layer->private_display = private_display;
360                 private_layer->private_output = private_output;
361                 private_layer->layer_backend = layer_backend;
362
363                 LIST_INITHEAD(&private_layer->capture_list);
364
365                 private_layer->usable = 1;
366         } else
367                 _tdm_display_destroy_caps_layer(&private_layer->caps);
368
369         ret = _tdm_display_update_caps_layer(private_display, layer_backend,
370                                              &private_layer->caps);
371         if (ret != TDM_ERROR_NONE)
372                 goto failed_update;
373
374         return TDM_ERROR_NONE;
375 failed_update:
376         _tdm_display_destroy_private_layer(private_layer);
377         return ret;
378 }
379
380 INTERN void
381 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
382                      void *user_data)
383 {
384         tdm_private_display *private_display;
385         tdm_private_output *private_output = user_data;
386         tdm_value value;
387
388         TDM_RETURN_IF_FAIL(private_output);
389
390         private_display = private_output->private_display;
391
392         if (!tdm_thread_in_display_thread(private_display)) {
393                 tdm_thread_cb_output_status output_status;
394                 tdm_error ret;
395
396                 output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
397                 output_status.base.length = sizeof output_status;
398                 output_status.output_stamp = private_output->stamp;
399                 output_status.status = status;
400                 output_status.user_data = user_data;
401
402                 ret = tdm_thread_send_cb(private_display, &output_status.base);
403                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
404
405                 return;
406         }
407
408         value.u32 = status;
409         tdm_output_call_change_handler_internal(private_output,
410                                                 TDM_OUTPUT_CHANGE_CONNECTION,
411                                                 value);
412 }
413
414 static tdm_error
415 _tdm_display_update_output(tdm_private_display *private_display,
416                            tdm_output *output_backend, int pipe)
417 {
418         tdm_func_output *func_output = &private_display->func_output;
419         tdm_private_output *private_output = NULL;
420         tdm_layer **layers = NULL;
421         int layer_count = 0, i;
422         tdm_error ret;
423
424         private_output = _tdm_display_find_private_output(private_display,
425                          output_backend);
426         if (!private_output) {
427                 private_output = calloc(1, sizeof(tdm_private_output));
428                 TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
429
430                 private_output->stamp = tdm_helper_get_time_in_millis();
431                 while (tdm_display_find_output_stamp(private_display, private_output->stamp))
432                         private_output->stamp++;
433
434                 LIST_ADD(&private_output->link, &private_display->output_list);
435
436                 private_output->private_display = private_display;
437                 private_output->output_backend = output_backend;
438                 private_output->pipe = pipe;
439
440                 LIST_INITHEAD(&private_output->layer_list);
441                 LIST_INITHEAD(&private_output->capture_list);
442                 LIST_INITHEAD(&private_output->vblank_handler_list);
443                 LIST_INITHEAD(&private_output->commit_handler_list);
444                 LIST_INITHEAD(&private_output->change_handler_list);
445
446                 if (func_output->output_set_status_handler) {
447                         private_output->regist_change_cb = 1;
448                         ret = func_output->output_set_status_handler(output_backend,
449                                                                      tdm_output_cb_status,
450                                                                      private_output);
451                         if (ret != TDM_ERROR_NONE)
452                                 goto failed_update;
453                 }
454         } else
455                 _tdm_display_destroy_caps_output(&private_output->caps);
456
457         ret = _tdm_display_update_caps_output(private_display, output_backend,
458                                               &private_output->caps);
459         if (ret != TDM_ERROR_NONE)
460                 return ret;
461
462         layers = func_output->output_get_layers(output_backend, &layer_count, &ret);
463         if (ret != TDM_ERROR_NONE)
464                 goto failed_update;
465
466         for (i = 0; i < layer_count; i++) {
467                 ret = _tdm_display_update_layer(private_display, private_output, layers[i]);
468                 if (ret != TDM_ERROR_NONE)
469                         goto failed_update;
470         }
471
472         free(layers);
473
474         return TDM_ERROR_NONE;
475 failed_update:
476         _tdm_display_destroy_private_output(private_output);
477         free(layers);
478         return ret;
479 }
480
481 static tdm_error
482 _tdm_display_update_internal(tdm_private_display *private_display,
483                              int only_display)
484 {
485         tdm_func_display *func_display = &private_display->func_display;
486         tdm_output **outputs = NULL;
487         int output_count = 0, i;
488         tdm_error ret;
489
490         LIST_INITHEAD(&private_display->output_list);
491         LIST_INITHEAD(&private_display->pp_list);
492         LIST_INITHEAD(&private_display->capture_list);
493
494         if (!only_display) {
495                 ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
496                 if (ret != TDM_ERROR_NONE)
497                         goto failed_update;
498
499                 ret = _tdm_display_update_caps_capture(private_display,
500                                                        &private_display->caps_capture);
501                 if (ret != TDM_ERROR_NONE)
502                         goto failed_update;
503         }
504
505         outputs = func_display->display_get_outputs(private_display->bdata,
506                         &output_count, &ret);
507         if (ret != TDM_ERROR_NONE)
508                 goto failed_update;
509
510         for (i = 0; i < output_count; i++) {
511                 ret = _tdm_display_update_output(private_display, outputs[i], i);
512                 if (ret != TDM_ERROR_NONE)
513                         goto failed_update;
514         }
515
516         free(outputs);
517
518         return TDM_ERROR_NONE;
519
520 failed_update:
521         _tdm_display_destroy_private_display(private_display);
522         free(outputs);
523         return ret;
524 }
525
526 EXTERN tdm_error
527 tdm_display_update(tdm_display *dpy)
528 {
529         tdm_private_display *private_display;
530         tdm_error ret;
531
532         TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER);
533
534         private_display = dpy;
535         _pthread_mutex_lock(&private_display->lock);
536
537         ret = _tdm_display_update_internal(private_display, 1);
538
539         _pthread_mutex_unlock(&private_display->lock);
540
541         return ret;
542 }
543
544 #define SUFFIX_MODULE    ".so"
545 #define DEFAULT_MODULE   "libtdm-default"SUFFIX_MODULE
546
547 int tdm_debug;
548 int tdm_debug_buffer;
549 int tdm_debug_thread;
550 int tdm_debug_mutex;
551
552 static tdm_private_display *g_private_display;
553 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
554
555 static tdm_error
556 _tdm_display_check_module(tdm_backend_module *module)
557 {
558         const char *name;
559         const char *vendor;
560         int major, minor;
561         int abimaj, abimin;
562
563         abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
564         abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
565
566         TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
567
568         name = module->name ? module->name : "unknown";
569         vendor = module->vendor ? module->vendor : "unknown";
570         major = TDM_BACKEND_GET_ABI_MAJOR(module->abi_version);
571         minor = TDM_BACKEND_GET_ABI_MINOR(module->abi_version);
572
573         TDM_INFO("TDM module name: %s", name);
574         TDM_INFO("'%s' vendor: %s", name, vendor);
575         TDM_INFO("'%s' version: %d.%d", name, major, minor);
576
577         if (major != abimaj) {
578                 TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
579                 return TDM_ERROR_BAD_MODULE;
580         }
581
582         if (minor > abimin) {
583                 TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
584                 return TDM_ERROR_BAD_MODULE;
585         }
586
587         if (!module->init) {
588                 TDM_ERR("'%s' doesn't have init function", name);
589                 return TDM_ERROR_BAD_MODULE;
590         }
591
592         if (!module->deinit) {
593                 TDM_ERR("'%s' doesn't have deinit function", name);
594                 return TDM_ERROR_BAD_MODULE;
595         }
596
597         return TDM_ERROR_NONE;
598 }
599
600 static tdm_error
601 _tdm_display_check_backend_functions(tdm_private_display *private_display)
602 {
603         tdm_func_display *func_display = &private_display->func_display;
604         tdm_func_output *func_output = &private_display->func_output;
605         tdm_func_layer *func_layer = &private_display->func_layer;
606         tdm_error ret;
607
608         /* below functions should be implemented in backend side */
609
610         TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_BAD_MODULE);
611         TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capabilitiy,
612                                TDM_ERROR_BAD_MODULE);
613         TDM_RETURN_VAL_IF_FAIL(func_display->display_get_outputs, TDM_ERROR_BAD_MODULE);
614         TDM_RETURN_VAL_IF_FAIL(func_output->output_get_capability,
615                                TDM_ERROR_BAD_MODULE);
616         TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE);
617         TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE);
618
619         ret = func_display->display_get_capabilitiy(private_display->bdata,
620                         &private_display->caps_display);
621         if (ret != TDM_ERROR_NONE) {
622                 TDM_ERR("display_get_capabilitiy() failed");
623                 return TDM_ERROR_BAD_MODULE;
624         }
625
626         if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
627                 tdm_func_pp *func_pp = &private_display->func_pp;
628                 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability,
629                                        TDM_ERROR_BAD_MODULE);
630                 TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE);
631                 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE);
632                 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_commit, TDM_ERROR_BAD_MODULE);
633                 TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE);
634         }
635
636         if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
637                 tdm_func_capture *func_capture = &private_display->func_capture;
638                 TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability,
639                                        TDM_ERROR_BAD_MODULE);
640                 TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture,
641                                        TDM_ERROR_BAD_MODULE);
642                 TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE);
643                 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE);
644                 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE);
645                 TDM_RETURN_VAL_IF_FAIL(func_capture->capture_set_done_handler,
646                                        TDM_ERROR_BAD_MODULE);
647         }
648
649         return TDM_ERROR_NONE;
650 }
651
652 static tdm_error
653 _tdm_display_load_module_with_file(tdm_private_display *private_display,
654                                    const char *file)
655 {
656         char path[PATH_MAX] = {0,};
657         tdm_backend_module *module_data;
658         void *module;
659         tdm_error ret;
660
661         snprintf(path, sizeof(path), TDM_MODULE_PATH "/%s", file);
662
663         TDM_TRACE_BEGIN(Load_Backend);
664
665         module = dlopen(path, RTLD_LAZY);
666         if (!module) {
667                 TDM_ERR("failed to load module: %s(%s)", dlerror(), file);
668                 TDM_TRACE_END();
669                 return TDM_ERROR_BAD_MODULE;
670         }
671
672         module_data = dlsym(module, "tdm_backend_module_data");
673         if (!module_data) {
674                 TDM_ERR("'%s' doesn't have data object", file);
675                 ret = TDM_ERROR_BAD_MODULE;
676                 TDM_TRACE_END();
677                 goto failed_load;
678         }
679
680         private_display->module_data = module_data;
681         private_display->module = module;
682
683         /* check if version, init() and deinit() are valid or not */
684         ret = _tdm_display_check_module(module_data);
685         if (ret != TDM_ERROR_NONE)
686                 goto failed_load;
687
688         TDM_TRACE_END();
689
690         /* We don't care if backend_data is NULL or not. It's up to backend. */
691         TDM_TRACE_BEGIN(Init_Backend);
692         private_display->bdata = module_data->init((tdm_display *)private_display,
693                                  &ret);
694         TDM_TRACE_END();
695         if (ret != TDM_ERROR_NONE) {
696                 TDM_ERR("'%s' init failed", file);
697                 goto failed_load;
698         }
699
700         ret = _tdm_display_check_backend_functions(private_display);
701         if (ret != TDM_ERROR_NONE) {
702                 module_data->deinit(private_display->bdata);
703                 private_display->bdata = NULL;
704                 goto failed_load;
705         }
706
707         TDM_INFO("Success to load module(%s)", file);
708
709         return TDM_ERROR_NONE;
710 failed_load:
711         dlclose(module);
712         private_display->module_data = NULL;
713         private_display->module = NULL;
714         return ret;
715 }
716
717 static tdm_error
718 _tdm_display_load_module(tdm_private_display *private_display)
719 {
720         const char *module_name;
721         struct dirent **namelist;
722         int n;
723         tdm_error ret = 0;
724
725         module_name = getenv("TDM_MODULE");
726         if (!module_name)
727                 module_name = DEFAULT_MODULE;
728
729         /* load bufmgr priv from default lib */
730         ret = _tdm_display_load_module_with_file(private_display, module_name);
731         if (ret == TDM_ERROR_NONE)
732                 return TDM_ERROR_NONE;
733
734         /* load bufmgr priv from configured path */
735         n = scandir(TDM_MODULE_PATH, &namelist, 0, alphasort);
736         if (n < 0) {
737                 TDM_ERR("no module in '%s'\n", TDM_MODULE_PATH);
738                 return TDM_ERROR_BAD_MODULE;
739         }
740
741         ret = TDM_ERROR_BAD_MODULE;
742         while (n--) {
743                 if (ret < 0 && strstr(namelist[n]->d_name, SUFFIX_MODULE))
744                         ret = _tdm_display_load_module_with_file(private_display, namelist[n]->d_name);
745
746                 free(namelist[n]);
747         }
748         free(namelist);
749
750         return ret;
751 }
752
753 static void
754 _tdm_display_unload_module(tdm_private_display *private_display)
755 {
756         if (private_display->module_data)
757                 private_display->module_data->deinit(private_display->bdata);
758         if (private_display->module)
759                 dlclose(private_display->module);
760
761         private_display->bdata = NULL;
762         private_display->module_data = NULL;
763         private_display->module = NULL;
764 }
765
766 EXTERN tdm_display *
767 tdm_display_init(tdm_error *error)
768 {
769         tdm_private_display *private_display = NULL;
770         const char *debug;
771         tdm_error ret;
772
773         _pthread_mutex_lock(&gLock);
774
775         if (g_private_display) {
776                 g_private_display->init_count++;
777                 _pthread_mutex_unlock(&gLock);
778                 if (error)
779                         *error = TDM_ERROR_NONE;
780                 return g_private_display;
781         }
782
783         debug = getenv("TDM_DEBUG");
784         if (debug && (strstr(debug, "1")))
785                 tdm_debug = 1;
786
787         debug = getenv("TDM_DEBUG_BUFFER");
788         if (debug && (strstr(debug, "1")))
789                 tdm_debug_buffer = 1;
790
791         debug = getenv("TDM_DEBUG_THREAD");
792         if (debug && (strstr(debug, "1")))
793                 tdm_debug_thread = 1;
794
795         debug = getenv("TDM_DEBUG_MUTEX");
796         if (debug && (strstr(debug, "1")))
797                 tdm_debug_mutex = 1;
798
799         private_display = calloc(1, sizeof(tdm_private_display));
800         if (!private_display) {
801                 ret = TDM_ERROR_OUT_OF_MEMORY;
802                 TDM_ERR("'private_display != NULL' failed");
803                 goto failed_alloc;
804         }
805
806         if (pthread_mutex_init(&private_display->lock, NULL)) {
807                 ret = TDM_ERROR_OPERATION_FAILED;
808                 TDM_ERR("mutex init failed: %m");
809                 goto failed_mutex_init;
810         }
811
812         ret = tdm_event_loop_init(private_display);
813         if (ret != TDM_ERROR_NONE)
814                 goto failed_event;
815
816         ret = tdm_thread_init(private_display);
817         if (ret != TDM_ERROR_NONE)
818                 goto failed_thread;
819
820         ret = _tdm_display_load_module(private_display);
821         if (ret != TDM_ERROR_NONE)
822                 goto failed_load;
823
824         TDM_TRACE_BEGIN(Update_Display);
825         ret = _tdm_display_update_internal(private_display, 0);
826         TDM_TRACE_END();
827         if (ret != TDM_ERROR_NONE)
828                 goto failed_update;
829
830         tdm_event_loop_create_backend_source(private_display);
831
832         private_display->init_count = 1;
833
834         g_private_display = private_display;
835
836         if (error)
837                 *error = TDM_ERROR_NONE;
838
839         _pthread_mutex_unlock(&gLock);
840
841         return (tdm_display *)private_display;
842
843 failed_update:
844         _tdm_display_unload_module(private_display);
845 failed_load:
846         tdm_thread_deinit(private_display);
847 failed_thread:
848         tdm_event_loop_deinit(private_display);
849 failed_event:
850         pthread_mutex_destroy(&private_display->lock);
851 failed_mutex_init:
852         free(private_display);
853 failed_alloc:
854         tdm_debug = 0;
855         tdm_debug_buffer = 0;
856         if (error)
857                 *error = ret;
858         _pthread_mutex_unlock(&gLock);
859         return NULL;
860 }
861
862 EXTERN void
863 tdm_display_deinit(tdm_display *dpy)
864 {
865         tdm_private_display *private_display = dpy;
866
867         if (!private_display)
868                 return;
869
870         _pthread_mutex_lock(&gLock);
871
872         private_display->init_count--;
873         if (private_display->init_count > 0) {
874                 _pthread_mutex_unlock(&gLock);
875                 return;
876         }
877
878         _pthread_mutex_lock(&private_display->lock);
879
880         tdm_thread_deinit(private_display);
881         tdm_event_loop_deinit(private_display);
882
883         _tdm_display_destroy_private_display(private_display);
884         _tdm_display_unload_module(private_display);
885
886         tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
887
888         _pthread_mutex_unlock(&private_display->lock);
889
890         pthread_mutex_destroy(&private_display->lock);
891         free(private_display);
892         g_private_display = NULL;
893         tdm_debug = 0;
894         tdm_debug_buffer = 0;
895
896         _pthread_mutex_unlock(&gLock);
897 }
898