1 /**************************************************************************
5 Copyright 2012-2021 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>
8 Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 #include "tbm_bufmgr_int.h"
35 #include "tbm_bufmgr_backend.h"
36 #include "tbm_drm_helper.h"
38 #define PREFIX_LIB "libtbm_"
39 #define SUFFIX_LIB ".so"
40 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
42 /* values to indicate unspecified fields in XF86ModReqInfo. */
43 #define MAJOR_UNSPEC 0xFF
44 #define MINOR_UNSPEC 0xFF
45 #define PATCH_UNSPEC 0xFFFF
46 #define ABI_VERS_UNSPEC 0xFFFFFFFF
48 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
49 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
50 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
51 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
52 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
57 _tbm_module_copy_data_to_bufmgr(tbm_module *module, tbm_bufmgr bufmgr, int reset)
60 bufmgr->module_data = module->module_data;
61 bufmgr->backend = module->backend;
63 bufmgr->backend_module_data = module->backend_module_data;
64 bufmgr->bufmgr_data = module->bufmgr_data;
65 bufmgr->bufmgr_func = module->bufmgr_func;
66 bufmgr->bo_func = module->bo_func;
68 bufmgr->use_hal_tbm = module->use_hal_tbm;
69 bufmgr->auth_wl_socket_created = module->auth_wl_socket_created;
70 bufmgr->auth_fd = module->auth_fd;
71 bufmgr->hal_backend = module->hal_backend;
72 bufmgr->hal_bufmgr = module->hal_bufmgr;
74 bufmgr->module_data = NULL;
75 bufmgr->backend = NULL;
77 bufmgr->backend_module_data = NULL;
78 bufmgr->bufmgr_data = NULL;
79 bufmgr->bufmgr_func = NULL;
80 bufmgr->bo_func = NULL;
82 bufmgr->use_hal_tbm = 0;
83 bufmgr->auth_wl_socket_created = 0;
85 bufmgr->hal_backend = NULL;
86 bufmgr->hal_bufmgr = NULL;
91 _tbm_backend_load_hal_tbm(tbm_module *module)
93 hal_tbm_backend *hal_backend = NULL;
94 hal_tbm_bufmgr_capability capability;
95 hal_tbm_bufmgr *hal_bufmgr;
96 hal_tbm_error ret = HAL_TBM_ERROR_NONE;
97 hal_tbm_fd auth_drm_fd = -1;
99 hal_backend = hal_tbm_get_backend(&ret);
100 if (hal_backend == NULL || ret != HAL_TBM_ERROR_NONE) {
101 TBM_ERR("get backend fail");
105 hal_bufmgr = hal_tbm_backend_get_bufmgr(hal_backend, &ret);
106 if (hal_bufmgr == NULL || ret != HAL_TBM_ERROR_NONE) {
107 TBM_ERR("get hal_bufmgr fail");
108 goto get_backend_fail;
111 if (hal_tbm_backend_has_drm_device(hal_backend, &ret)) {
112 auth_drm_fd = hal_tbm_backend_get_master_drm_fd(hal_backend, &ret);
113 if (auth_drm_fd < 0) {
114 TBM_INFO("tbm_backend has no master drm_fd.");
116 auth_drm_fd = tbm_drm_helper_get_master_fd();
117 if (auth_drm_fd < 0) {
118 TBM_INFO("libtbm requests an authenticated drm_fd to a process(display server).");
119 if (!tbm_drm_helper_get_auth_info(&auth_drm_fd, NULL, NULL)) {
120 TBM_ERR("get auth drm_fd fail");
121 goto get_backend_fail;
124 TBM_INFO("libtbm gets a master drm_fd from libtdm via tbm_drm_helper.");
127 TBM_INFO("libtbm sends a master drm_fd as an authentiated drm_fd to tbm_backend.");
128 ret = hal_tbm_backend_set_authenticated_drm_fd(hal_backend, auth_drm_fd);
129 if (ret != HAL_TBM_ERROR_NONE) {
130 TBM_ERR("hal_tbm_backend_set_authenticated_drm_fd failed.");
131 goto get_backend_fail;
134 TBM_INFO("tbm_backend has a master drm_fd.");
136 tbm_drm_helper_set_tbm_master_fd(auth_drm_fd);
138 tbm_drm_helper_set_fd(auth_drm_fd);
141 capability = hal_tbm_bufmgr_get_capabilities(hal_bufmgr, &ret);
142 if (ret != HAL_TBM_ERROR_NONE) {
143 TBM_ERR("hal_tbm_bufmgr_get_capabilities fail.");
144 goto get_backend_fail;
147 if (capability == HAL_TBM_BUFMGR_CAPABILITY_NONE) {
148 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
149 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
150 goto get_backend_fail;
152 if (!(capability & HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
153 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
154 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
155 goto get_backend_fail;
158 module->bufmgr->capabilities = capability;
160 module->hal_backend = hal_backend;
161 module->hal_bufmgr = hal_bufmgr;
163 module->use_hal_tbm = 1;
165 TBM_INFO("use HAL-TBM_API");
170 if (auth_drm_fd >= 0)
172 hal_tbm_put_backend(hal_backend);
177 _check_version(TBMModuleVersionInfo *data)
179 int backend_module_major, backend_module_minor;
180 int tbm_backend_major, tbm_backend_minor;
182 backend_module_major = GET_ABI_MAJOR(data->abiversion);
183 backend_module_minor = GET_ABI_MINOR(data->abiversion);
185 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
186 data->modname ? data->modname : "UNKNOWN!",
187 data->vendor ? data->vendor : "UNKNOWN!", backend_module_major, backend_module_minor);
189 tbm_backend_major = GET_ABI_MAJOR(TBM_ABI_VERSION);
190 tbm_backend_minor = GET_ABI_MINOR(TBM_ABI_VERSION);
192 TBM_DBG("TBM ABI version %d.%d\n",
193 tbm_backend_major, tbm_backend_minor);
195 if (backend_module_major != tbm_backend_major) {
196 TBM_ERR("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
197 backend_module_major, tbm_backend_major);
199 } else if (backend_module_minor > tbm_backend_minor) {
200 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
201 backend_module_minor, tbm_backend_minor);
209 _tbm_backend_check_bufmgr_func(tbm_backend_bufmgr_func *bufmgr_func)
211 TBM_RETURN_VAL_IF_FAIL(bufmgr_func, 0); /* mandatory symbol */
212 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0); /* mandatory symbol */
213 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_bind_native_display, 0); /* mandatory symbol */
214 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_supported_formats, 0); /* mandatory symbol */
215 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_plane_data, 0); /* mandatory symbol */
216 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, 0); /* mandatory symbol */
217 if (!bufmgr_func->bufmgr_alloc_bo_with_format)
218 TBM_DBG("No bufmgr_func->bufmgr_alloc_bo_with_format.");
219 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_import_fd, 0); /* mandatory symbol */
220 if (!bufmgr_func->bufmgr_import_key)
221 TBM_DBG("No bufmgr_func->bo_export_key.");
227 _tbm_backend_check_bufmgr_bo(tbm_backend_bo_func *bo_func)
229 TBM_RETURN_VAL_IF_FAIL(bo_func, 0); /* mandatory symbol */
230 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_free, 0); /* mandatory symbol */
231 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_size, 0); /* mandatory symbol */
232 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_memory_types, 0); /* mandatory symbol */
233 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_handle, 0); /* mandatory symbol */
234 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_map, 0); /* mandatory symbol */
235 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_unmap, 0); /* mandatory symbol */
236 if (!bo_func->bo_lock)
237 TBM_DBG("No bo_func->bo_lock.");
238 if (!bo_func->bo_unlock)
239 TBM_DBG("No bo_func->bo_unlock.");
240 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_export_fd, 0); /* mandatory symbol */
241 if (!bo_func->bo_export_key)
242 TBM_INFO("No bo_func->bo_export_key.");
248 _tbm_backend_load_module(tbm_module *module, const char *file)
250 char path[PATH_MAX] = {0, };
251 void *module_data = NULL;
252 tbm_backend_module *backend_module_data = NULL;
253 tbm_backend_bufmgr_data *bufmgr_data = NULL;
254 int backend_module_major, backend_module_minor;
255 int tbm_backend_major, tbm_backend_minor;
258 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
260 module_data = dlopen(path, RTLD_LAZY);
262 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
266 backend_module_data = dlsym(module_data, "tbm_backend_module_data");
267 if (!backend_module_data) {
268 TBM_ERR("Error: module does not have data object.\n");
272 tbm_backend_major = GET_ABI_MAJOR(TBM_BACKEND_ABI_LATEST_VERSION);
273 tbm_backend_minor = GET_ABI_MINOR(TBM_BACKEND_ABI_LATEST_VERSION);
274 TBM_INFO("TBM Backend ABI version %d.%d\n", tbm_backend_major, tbm_backend_minor);
276 backend_module_major = GET_ABI_MAJOR(backend_module_data->abi_version);
277 backend_module_minor = GET_ABI_MINOR(backend_module_data->abi_version);
279 TBM_INFO("TBM module %s: vendor=\"%s\" Backend ABI version=%d.%d\n",
280 backend_module_data->name ? backend_module_data->name : "UNKNOWN!",
281 backend_module_data->vendor ? backend_module_data->vendor : "UNKNOWN!",
282 backend_module_major, backend_module_minor);
284 if (backend_module_major > tbm_backend_major) {
285 TBM_ERR("TBM module ABI major ver(%d) is newer than the TBM's ver(%d)\n",
286 backend_module_major, tbm_backend_major);
288 } else if (backend_module_minor > tbm_backend_minor) {
289 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
290 backend_module_minor, tbm_backend_minor);
294 if (!backend_module_data->init) {
295 TBM_ERR("Error: module does not supply init symbol.\n");
299 if (!backend_module_data->deinit) {
300 TBM_ERR("Error: module does not supply deinit symbol.\n");
304 bufmgr_data = backend_module_data->init((tbm_bufmgr)module, &error);
306 TBM_ERR("Fail to init module(%s)\n", file);
310 /* check the mandatory symbols of the backend module */
311 if (!_tbm_backend_check_bufmgr_func(module->bufmgr_func)) {
312 TBM_ERR("Fail to check the bufmgr_func symboles.");
316 if (!_tbm_backend_check_bufmgr_bo(module->bo_func)) {
317 TBM_ERR("Fail to check the bufmgr_bo symboles.");
321 /* get the capability */
322 module->bufmgr->capabilities = module->bufmgr->bufmgr_func->bufmgr_get_capabilities(bufmgr_data, &error);
323 if (module->bufmgr->capabilities == TBM_BUFMGR_CAPABILITY_NONE) {
324 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
325 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
329 if (!(module->bufmgr->capabilities & TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
330 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
331 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
335 module->module_data = module_data;
336 module->backend_module_data = backend_module_data;
337 module->bufmgr_data = bufmgr_data;
339 TBM_INFO("Success to load module(%s)\n", file);
345 module->backend_module_data->deinit(bufmgr_data);
347 dlclose(module_data);
353 _tbm_backend_load_bufmgr_module(tbm_module *module, int fd, const char *file)
355 char path[PATH_MAX] = {0, };
356 TBMModuleVersionInfo *vers;
357 TBMModuleData *initdata;
361 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
363 module_data = dlopen(path, RTLD_LAZY);
365 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
369 initdata = dlsym(module_data, "tbmModuleData");
371 TBM_ERR("Error: module does not have data object.\n");
375 vers = initdata->vers;
377 TBM_ERR("Error: module does not supply version information.\n");
381 init = initdata->init;
383 TBM_ERR("Error: module does not supply init symbol.\n");
387 if (!_check_version(vers)) {
388 TBM_ERR("Fail to check version.\n");
392 if (!init((tbm_bufmgr)module, fd)) {
393 TBM_ERR("Fail to init module(%s)\n", file);
397 if (!module->backend || !module->backend->priv) {
398 TBM_ERR("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
402 module->module_data = module_data;
404 TBM_DBG("Success to load module(%s)\n", file);
409 dlclose(module_data);
416 tbm_module_load(tbm_bufmgr bufmgr, int fd)
419 struct dirent **namelist;
422 module = calloc(1, sizeof(struct _tbm_module));
424 TBM_ERR("fail to allocate the memory");
427 module->bufmgr = bufmgr;
429 /* try to load the hal-tbm backend module */
430 ret = _tbm_backend_load_hal_tbm(module);
432 module->type = TBM_MODULE_TYPE_HAL_TBM;
436 /* try to load the new backend module */
437 ret = _tbm_backend_load_module(module, DEFAULT_LIB);
439 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
443 /* try to load the old(deprecated) backend mdoule */
444 ret = _tbm_backend_load_bufmgr_module(module, fd, DEFAULT_LIB);
446 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
450 /* load bufmgr priv from configured path */
451 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
453 TBM_ERR("no files : %s\n", BUFMGR_MODULE_DIR);
454 tbm_module_unload(module);
459 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
460 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
462 if (p && !strcmp(p, SUFFIX_LIB)) {
463 ret = _tbm_backend_load_module(module, namelist[n]->d_name);
465 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
467 ret = _tbm_backend_load_bufmgr_module(module, fd, namelist[n]->d_name);
468 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
485 _tbm_module_copy_data_to_bufmgr(module, module->bufmgr, 0);
491 tbm_module_unload(tbm_module *module)
493 if (module->use_hal_tbm) {
494 if (module->auth_wl_socket_created) {
495 tbm_drm_helper_wl_auth_server_deinit();
496 close(module->auth_fd);
498 tbm_drm_helper_unset_tbm_master_fd();
499 tbm_drm_helper_unset_fd();
501 hal_tbm_put_backend(module->hal_backend);
502 module->hal_backend = NULL;
503 module->hal_bufmgr = NULL;
504 module->use_hal_tbm = 0;
506 if (module->backend_module_data) {
507 module->backend_module_data->deinit(module->bufmgr_data);
508 module->bo_func = NULL;
509 module->bufmgr_func = NULL;
510 module->bufmgr_data = NULL;
511 module->backend_module_data = NULL;
513 module->backend->bufmgr_deinit(module->backend->priv);
514 module->backend->priv = NULL;
515 tbm_backend_free(module->backend);
516 module->backend = NULL;
519 dlclose(module->module_data);
522 _tbm_module_copy_data_to_bufmgr(module, module->bufmgr, 1);
523 module->bufmgr = NULL;