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 *hal_bufmgr;
95 hal_tbm_error ret = HAL_TBM_ERROR_NONE;
96 hal_tbm_fd auth_drm_fd = -1;
98 hal_backend = hal_tbm_get_backend(&ret);
99 if (hal_backend == NULL || ret != HAL_TBM_ERROR_NONE) {
100 TBM_ERR("get backend fail");
104 hal_bufmgr = hal_tbm_backend_get_bufmgr(hal_backend, &ret);
105 if (hal_bufmgr == NULL || ret != HAL_TBM_ERROR_NONE) {
106 TBM_ERR("get hal_bufmgr fail");
107 goto get_backend_fail;
110 if (hal_tbm_backend_has_drm_device(hal_backend, &ret)) {
111 auth_drm_fd = hal_tbm_backend_get_master_drm_fd(hal_backend, &ret);
112 if (auth_drm_fd < 0) {
113 TBM_INFO("tbm_backend has no master drm_fd.");
115 auth_drm_fd = tbm_drm_helper_get_master_fd();
116 if (auth_drm_fd < 0) {
117 TBM_INFO("libtbm requests an authenticated drm_fd to a process(display server).");
118 if (!tbm_drm_helper_get_auth_info(&auth_drm_fd, NULL, NULL)) {
119 TBM_ERR("get auth drm_fd fail");
120 goto get_backend_fail;
123 TBM_INFO("libtbm gets a master drm_fd from libtdm via tbm_drm_helper.");
126 TBM_INFO("libtbm sends a master drm_fd as an authentiated drm_fd to tbm_backend.");
127 ret = hal_tbm_backend_set_authenticated_drm_fd(hal_backend, auth_drm_fd);
128 if (ret != HAL_TBM_ERROR_NONE) {
129 TBM_ERR("hal_tbm_backend_set_authenticated_drm_fd failed.");
130 goto get_backend_fail;
133 TBM_INFO("tbm_backend has a master drm_fd.");
135 tbm_drm_helper_set_tbm_master_fd(auth_drm_fd);
137 tbm_drm_helper_set_fd(auth_drm_fd);
140 module->hal_backend = hal_backend;
141 module->hal_bufmgr = hal_bufmgr;
143 module->use_hal_tbm = 1;
145 TBM_INFO("use HAL-TBM_API");
150 if (auth_drm_fd >= 0)
152 hal_tbm_put_backend(hal_backend);
157 _check_version(TBMModuleVersionInfo *data)
159 int backend_module_major, backend_module_minor;
160 int tbm_backend_major, tbm_backend_minor;
162 backend_module_major = GET_ABI_MAJOR(data->abiversion);
163 backend_module_minor = GET_ABI_MINOR(data->abiversion);
165 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
166 data->modname ? data->modname : "UNKNOWN!",
167 data->vendor ? data->vendor : "UNKNOWN!", backend_module_major, backend_module_minor);
169 tbm_backend_major = GET_ABI_MAJOR(TBM_ABI_VERSION);
170 tbm_backend_minor = GET_ABI_MINOR(TBM_ABI_VERSION);
172 TBM_DBG("TBM ABI version %d.%d\n",
173 tbm_backend_major, tbm_backend_minor);
175 if (backend_module_major != tbm_backend_major) {
176 TBM_ERR("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
177 backend_module_major, tbm_backend_major);
179 } else if (backend_module_minor > tbm_backend_minor) {
180 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
181 backend_module_minor, tbm_backend_minor);
189 _tbm_backend_check_bufmgr_func(tbm_backend_bufmgr_func *bufmgr_func)
191 TBM_RETURN_VAL_IF_FAIL(bufmgr_func, 0); /* mandatory symbol */
192 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0); /* mandatory symbol */
193 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_bind_native_display, 0); /* mandatory symbol */
194 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_supported_formats, 0); /* mandatory symbol */
195 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_plane_data, 0); /* mandatory symbol */
196 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, 0); /* mandatory symbol */
197 if (!bufmgr_func->bufmgr_alloc_bo_with_format)
198 TBM_DBG("No bufmgr_func->bufmgr_alloc_bo_with_format.");
199 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_import_fd, 0); /* mandatory symbol */
200 if (!bufmgr_func->bufmgr_import_key)
201 TBM_DBG("No bufmgr_func->bo_export_key.");
207 _tbm_backend_check_bufmgr_bo(tbm_backend_bo_func *bo_func)
209 TBM_RETURN_VAL_IF_FAIL(bo_func, 0); /* mandatory symbol */
210 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_free, 0); /* mandatory symbol */
211 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_size, 0); /* mandatory symbol */
212 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_memory_types, 0); /* mandatory symbol */
213 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_handle, 0); /* mandatory symbol */
214 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_map, 0); /* mandatory symbol */
215 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_unmap, 0); /* mandatory symbol */
216 if (!bo_func->bo_lock)
217 TBM_DBG("No bo_func->bo_lock.");
218 if (!bo_func->bo_unlock)
219 TBM_DBG("No bo_func->bo_unlock.");
220 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_export_fd, 0); /* mandatory symbol */
221 if (!bo_func->bo_export_key)
222 TBM_INFO("No bo_func->bo_export_key.");
228 _tbm_backend_load_module(tbm_module *module, const char *file)
230 char path[PATH_MAX] = {0, };
231 void *module_data = NULL;
232 tbm_backend_module *backend_module_data = NULL;
233 tbm_backend_bufmgr_data *bufmgr_data = NULL;
234 int backend_module_major, backend_module_minor;
235 int tbm_backend_major, tbm_backend_minor;
238 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
240 module_data = dlopen(path, RTLD_LAZY);
242 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
246 backend_module_data = dlsym(module_data, "tbm_backend_module_data");
247 if (!backend_module_data) {
248 TBM_ERR("Error: module does not have data object.\n");
252 tbm_backend_major = GET_ABI_MAJOR(TBM_BACKEND_ABI_LATEST_VERSION);
253 tbm_backend_minor = GET_ABI_MINOR(TBM_BACKEND_ABI_LATEST_VERSION);
254 TBM_INFO("TBM Backend ABI version %d.%d\n", tbm_backend_major, tbm_backend_minor);
256 backend_module_major = GET_ABI_MAJOR(backend_module_data->abi_version);
257 backend_module_minor = GET_ABI_MINOR(backend_module_data->abi_version);
259 TBM_INFO("TBM module %s: vendor=\"%s\" Backend ABI version=%d.%d\n",
260 backend_module_data->name ? backend_module_data->name : "UNKNOWN!",
261 backend_module_data->vendor ? backend_module_data->vendor : "UNKNOWN!",
262 backend_module_major, backend_module_minor);
264 if (backend_module_major > tbm_backend_major) {
265 TBM_ERR("TBM module ABI major ver(%d) is newer than the TBM's ver(%d)\n",
266 backend_module_major, tbm_backend_major);
268 } else if (backend_module_minor > tbm_backend_minor) {
269 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
270 backend_module_minor, tbm_backend_minor);
274 if (!backend_module_data->init) {
275 TBM_ERR("Error: module does not supply init symbol.\n");
279 if (!backend_module_data->deinit) {
280 TBM_ERR("Error: module does not supply deinit symbol.\n");
284 bufmgr_data = backend_module_data->init((tbm_bufmgr)module, &error);
286 TBM_ERR("Fail to init module(%s)\n", file);
290 /* check the mandatory symbols of the backend module */
291 if (!_tbm_backend_check_bufmgr_func(module->bufmgr_func)) {
292 TBM_ERR("Fail to check the bufmgr_func symboles.");
296 if (!_tbm_backend_check_bufmgr_bo(module->bo_func)) {
297 TBM_ERR("Fail to check the bufmgr_bo symboles.");
301 module->module_data = module_data;
302 module->backend_module_data = backend_module_data;
303 module->bufmgr_data = bufmgr_data;
305 TBM_INFO("Success to load module(%s)\n", file);
311 module->backend_module_data->deinit(bufmgr_data);
313 dlclose(module_data);
319 _tbm_backend_load_bufmgr_module(tbm_module *module, int fd, const char *file)
321 char path[PATH_MAX] = {0, };
322 TBMModuleVersionInfo *vers;
323 TBMModuleData *initdata;
327 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
329 module_data = dlopen(path, RTLD_LAZY);
331 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
335 initdata = dlsym(module_data, "tbmModuleData");
337 TBM_ERR("Error: module does not have data object.\n");
341 vers = initdata->vers;
343 TBM_ERR("Error: module does not supply version information.\n");
347 init = initdata->init;
349 TBM_ERR("Error: module does not supply init symbol.\n");
353 if (!_check_version(vers)) {
354 TBM_ERR("Fail to check version.\n");
358 if (!init((tbm_bufmgr)module, fd)) {
359 TBM_ERR("Fail to init module(%s)\n", file);
363 if (!module->backend || !module->backend->priv) {
364 TBM_ERR("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
368 module->module_data = module_data;
370 TBM_DBG("Success to load module(%s)\n", file);
375 dlclose(module_data);
382 tbm_module_load(tbm_bufmgr bufmgr, int fd)
385 struct dirent **namelist;
388 module = calloc(1, sizeof(struct _tbm_module));
390 TBM_ERR("fail to allocate the memory");
393 module->bufmgr = bufmgr;
395 /* try to load the hal-tbm backend module */
396 ret = _tbm_backend_load_hal_tbm(module);
398 module->type = TBM_MODULE_TYPE_HAL_TBM;
402 /* try to load the new backend module */
403 ret = _tbm_backend_load_module(module, DEFAULT_LIB);
405 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
409 /* try to load the old(deprecated) backend mdoule */
410 ret = _tbm_backend_load_bufmgr_module(module, fd, DEFAULT_LIB);
412 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
416 /* load bufmgr priv from configured path */
417 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
419 TBM_ERR("no files : %s\n", BUFMGR_MODULE_DIR);
420 tbm_module_unload(module);
425 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
426 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
428 if (p && !strcmp(p, SUFFIX_LIB)) {
429 ret = _tbm_backend_load_module(module, namelist[n]->d_name);
431 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
433 ret = _tbm_backend_load_bufmgr_module(module, fd, namelist[n]->d_name);
434 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
451 _tbm_module_copy_data_to_bufmgr(module, module->bufmgr, 0);
457 tbm_module_unload(tbm_module *module)
459 switch (module->type) {
460 case TBM_MODULE_TYPE_HAL_TBM:
461 if (module->auth_wl_socket_created) {
462 tbm_drm_helper_wl_auth_server_deinit();
463 close(module->auth_fd);
465 tbm_drm_helper_unset_tbm_master_fd();
466 tbm_drm_helper_unset_fd();
468 hal_tbm_put_backend(module->hal_backend);
469 module->hal_backend = NULL;
470 module->hal_bufmgr = NULL;
471 module->use_hal_tbm = 0;
473 case TBM_MODULE_TYPE_TBM_BACKEND:
474 module->backend_module_data->deinit(module->bufmgr_data);
475 module->bo_func = NULL;
476 module->bufmgr_func = NULL;
477 module->bufmgr_data = NULL;
478 module->backend_module_data = NULL;
480 dlclose(module->module_data);
482 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
483 module->backend->bufmgr_deinit(module->backend->priv);
484 module->backend->priv = NULL;
485 tbm_backend_free(module->backend);
486 module->backend = NULL;
488 dlclose(module->module_data);
491 TBM_ERR("Wrong module type:%d", module->type);
495 _tbm_module_copy_data_to_bufmgr(module, module->bufmgr, 1);
496 module->bufmgr = NULL;
502 tbm_module_bufmgr_get_capabilities(tbm_module *module)
504 tbm_error_e error = TBM_ERROR_NOT_SUPPORTED;
505 int capabilities = 0;
507 switch (module->type) {
508 case TBM_MODULE_TYPE_HAL_TBM:
509 capabilities = hal_tbm_bufmgr_get_capabilities(module->hal_bufmgr, (hal_tbm_error *)&error);
511 case TBM_MODULE_TYPE_TBM_BACKEND:
512 capabilities = module->bufmgr_func->bufmgr_get_capabilities(module->bufmgr_data, &error);
514 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
515 TBM_ERR("Do not support at tbm_bufmgr_backend.");
518 TBM_ERR("Wrong module type:%d", module->type);
522 if (error != TBM_ERROR_NONE) {
523 TBM_ERR("fail to get capabilities of bufmgr");