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_backend_load_hal_tbm(tbm_bufmgr bufmgr)
59 hal_tbm_backend *hal_backend = NULL;
60 hal_tbm_bufmgr_capability capability;
61 hal_tbm_bufmgr *hal_bufmgr;
62 hal_tbm_error ret = HAL_TBM_ERROR_NONE;
63 hal_tbm_fd auth_drm_fd = -1;
65 hal_backend = hal_tbm_get_backend(&ret);
66 if (hal_backend == NULL || ret != HAL_TBM_ERROR_NONE) {
67 TBM_ERR("get backend fail");
71 hal_bufmgr = hal_tbm_backend_get_bufmgr(hal_backend, &ret);
72 if (hal_bufmgr == NULL || ret != HAL_TBM_ERROR_NONE) {
73 TBM_ERR("get hal_bufmgr fail");
74 goto get_backend_fail;
77 if (hal_tbm_backend_has_drm_device(hal_backend, &ret)) {
78 auth_drm_fd = hal_tbm_backend_get_master_drm_fd(hal_backend, &ret);
79 if (auth_drm_fd < 0) {
80 TBM_INFO("tbm_backend has no master drm_fd.");
82 auth_drm_fd = tbm_drm_helper_get_master_fd();
83 if (auth_drm_fd < 0) {
84 TBM_INFO("libtbm requests an authenticated drm_fd to a process(display server).");
85 if (!tbm_drm_helper_get_auth_info(&auth_drm_fd, NULL, NULL)) {
86 TBM_ERR("get auth drm_fd fail");
87 goto get_backend_fail;
90 TBM_INFO("libtbm gets a master drm_fd from libtdm via tbm_drm_helper.");
93 TBM_INFO("libtbm sends a master drm_fd as an authentiated drm_fd to tbm_backend.");
94 ret = hal_tbm_backend_set_authenticated_drm_fd(hal_backend, auth_drm_fd);
95 if (ret != HAL_TBM_ERROR_NONE) {
96 TBM_ERR("hal_tbm_backend_set_authenticated_drm_fd failed.");
97 goto get_backend_fail;
100 TBM_INFO("tbm_backend has a master drm_fd.");
102 tbm_drm_helper_set_tbm_master_fd(auth_drm_fd);
104 tbm_drm_helper_set_fd(auth_drm_fd);
107 capability = hal_tbm_bufmgr_get_capabilities(hal_bufmgr, &ret);
108 if (ret != HAL_TBM_ERROR_NONE) {
109 TBM_ERR("hal_tbm_bufmgr_get_capabilities fail.");
110 goto get_backend_fail;
113 if (capability == HAL_TBM_BUFMGR_CAPABILITY_NONE) {
114 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
115 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
116 goto get_backend_fail;
118 if (!(capability & HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
119 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
120 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
121 goto get_backend_fail;
123 bufmgr->capabilities = capability;
125 bufmgr->hal_backend = hal_backend;
126 bufmgr->hal_bufmgr = hal_bufmgr;
128 bufmgr->use_hal_tbm = 1;
130 TBM_INFO("use HAL-TBM_API");
135 if (auth_drm_fd >= 0)
137 hal_tbm_put_backend(hal_backend);
142 _check_version(TBMModuleVersionInfo *data)
144 int backend_module_major, backend_module_minor;
145 int tbm_backend_major, tbm_backend_minor;
147 backend_module_major = GET_ABI_MAJOR(data->abiversion);
148 backend_module_minor = GET_ABI_MINOR(data->abiversion);
150 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
151 data->modname ? data->modname : "UNKNOWN!",
152 data->vendor ? data->vendor : "UNKNOWN!", backend_module_major, backend_module_minor);
154 tbm_backend_major = GET_ABI_MAJOR(TBM_ABI_VERSION);
155 tbm_backend_minor = GET_ABI_MINOR(TBM_ABI_VERSION);
157 TBM_DBG("TBM ABI version %d.%d\n",
158 tbm_backend_major, tbm_backend_minor);
160 if (backend_module_major != tbm_backend_major) {
161 TBM_ERR("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
162 backend_module_major, tbm_backend_major);
164 } else if (backend_module_minor > tbm_backend_minor) {
165 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
166 backend_module_minor, tbm_backend_minor);
174 _tbm_backend_check_bufmgr_func(tbm_backend_bufmgr_func *bufmgr_func)
176 TBM_RETURN_VAL_IF_FAIL(bufmgr_func, 0); /* mandatory symbol */
177 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0); /* mandatory symbol */
178 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_bind_native_display, 0); /* mandatory symbol */
179 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_supported_formats, 0); /* mandatory symbol */
180 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_plane_data, 0); /* mandatory symbol */
181 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, 0); /* mandatory symbol */
182 if (!bufmgr_func->bufmgr_alloc_bo_with_format)
183 TBM_DBG("No bufmgr_func->bufmgr_alloc_bo_with_format.");
184 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_import_fd, 0); /* mandatory symbol */
185 if (!bufmgr_func->bufmgr_import_key)
186 TBM_DBG("No bufmgr_func->bo_export_key.");
192 _tbm_backend_check_bufmgr_bo(tbm_backend_bo_func *bo_func)
194 TBM_RETURN_VAL_IF_FAIL(bo_func, 0); /* mandatory symbol */
195 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_free, 0); /* mandatory symbol */
196 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_size, 0); /* mandatory symbol */
197 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_memory_types, 0); /* mandatory symbol */
198 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_handle, 0); /* mandatory symbol */
199 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_map, 0); /* mandatory symbol */
200 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_unmap, 0); /* mandatory symbol */
201 if (!bo_func->bo_lock)
202 TBM_DBG("No bo_func->bo_lock.");
203 if (!bo_func->bo_unlock)
204 TBM_DBG("No bo_func->bo_unlock.");
205 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_export_fd, 0); /* mandatory symbol */
206 if (!bo_func->bo_export_key)
207 TBM_INFO("No bo_func->bo_export_key.");
213 _tbm_backend_load_module(tbm_bufmgr bufmgr, const char *file)
215 char path[PATH_MAX] = {0, };
216 void *module_data = NULL;
217 tbm_backend_module *backend_module_data = NULL;
218 tbm_backend_bufmgr_data *bufmgr_data = NULL;
219 int backend_module_major, backend_module_minor;
220 int tbm_backend_major, tbm_backend_minor;
223 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
225 module_data = dlopen(path, RTLD_LAZY);
227 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
231 backend_module_data = dlsym(module_data, "tbm_backend_module_data");
232 if (!backend_module_data) {
233 TBM_ERR("Error: module does not have data object.\n");
237 tbm_backend_major = GET_ABI_MAJOR(TBM_BACKEND_ABI_LATEST_VERSION);
238 tbm_backend_minor = GET_ABI_MINOR(TBM_BACKEND_ABI_LATEST_VERSION);
239 TBM_INFO("TBM Backend ABI version %d.%d\n", tbm_backend_major, tbm_backend_minor);
241 backend_module_major = GET_ABI_MAJOR(backend_module_data->abi_version);
242 backend_module_minor = GET_ABI_MINOR(backend_module_data->abi_version);
244 TBM_INFO("TBM module %s: vendor=\"%s\" Backend ABI version=%d.%d\n",
245 backend_module_data->name ? backend_module_data->name : "UNKNOWN!",
246 backend_module_data->vendor ? backend_module_data->vendor : "UNKNOWN!",
247 backend_module_major, backend_module_minor);
249 if (backend_module_major > tbm_backend_major) {
250 TBM_ERR("TBM module ABI major ver(%d) is newer than the TBM's ver(%d)\n",
251 backend_module_major, tbm_backend_major);
253 } else if (backend_module_minor > tbm_backend_minor) {
254 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
255 backend_module_minor, tbm_backend_minor);
259 if (!backend_module_data->init) {
260 TBM_ERR("Error: module does not supply init symbol.\n");
264 if (!backend_module_data->deinit) {
265 TBM_ERR("Error: module does not supply deinit symbol.\n");
269 bufmgr_data = backend_module_data->init(bufmgr, &error);
271 TBM_ERR("Fail to init module(%s)\n", file);
275 /* check the mandatory symbols of the backend module */
276 if (!_tbm_backend_check_bufmgr_func(bufmgr->bufmgr_func)) {
277 TBM_ERR("Fail to check the bufmgr_func symboles.");
281 if (!_tbm_backend_check_bufmgr_bo(bufmgr->bo_func)) {
282 TBM_ERR("Fail to check the bufmgr_bo symboles.");
286 /* get the capability */
287 bufmgr->capabilities = bufmgr->bufmgr_func->bufmgr_get_capabilities(bufmgr_data, &error);
288 if (bufmgr->capabilities == TBM_BUFMGR_CAPABILITY_NONE) {
289 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
290 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
294 if (!(bufmgr->capabilities & TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
295 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
296 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
300 bufmgr->module_data = module_data;
301 bufmgr->backend_module_data = backend_module_data;
302 bufmgr->bufmgr_data = bufmgr_data;
304 TBM_INFO("Success to load module(%s)\n", file);
310 bufmgr->backend_module_data->deinit(bufmgr_data);
312 dlclose(module_data);
318 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
320 char path[PATH_MAX] = {0, };
321 TBMModuleVersionInfo *vers;
322 TBMModuleData *initdata;
326 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
328 module_data = dlopen(path, RTLD_LAZY);
330 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
334 initdata = dlsym(module_data, "tbmModuleData");
336 TBM_ERR("Error: module does not have data object.\n");
340 vers = initdata->vers;
342 TBM_ERR("Error: module does not supply version information.\n");
346 init = initdata->init;
348 TBM_ERR("Error: module does not supply init symbol.\n");
352 if (!_check_version(vers)) {
353 TBM_ERR("Fail to check version.\n");
357 if (!init(bufmgr, fd)) {
358 TBM_ERR("Fail to init module(%s)\n", file);
362 if (!bufmgr->backend || !bufmgr->backend->priv) {
363 TBM_ERR("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
367 bufmgr->module_data = module_data;
369 TBM_DBG("Success to load module(%s)\n", file);
374 dlclose(module_data);
381 tbm_module_load(tbm_bufmgr bufmgr, int fd)
384 struct dirent **namelist;
387 module = calloc(1, sizeof(struct _tbm_module));
389 TBM_ERR("fail to allocate the memory");
392 module->bufmgr = bufmgr;
394 /* try to load the hal-tbm backend module */
395 ret = _tbm_backend_load_hal_tbm(bufmgr);
397 module->type = TBM_MODULE_TYPE_HAL_TBM;
401 /* try to load the new backend module */
402 ret = _tbm_backend_load_module(bufmgr, DEFAULT_LIB);
404 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
408 /* try to load the old(deprecated) backend mdoule */
409 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
411 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
415 /* load bufmgr priv from configured path */
416 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
418 TBM_ERR("no files : %s\n", BUFMGR_MODULE_DIR);
423 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
424 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
426 if (p && !strcmp(p, SUFFIX_LIB)) {
427 ret = _tbm_backend_load_module(bufmgr, namelist[n]->d_name);
429 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
431 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
432 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
451 tbm_module_unload(tbm_module *module)
453 tbm_bufmgr bufmgr = module->bufmgr;
455 if (bufmgr->use_hal_tbm) {
456 if (bufmgr->auth_wl_socket_created) {
457 tbm_drm_helper_wl_auth_server_deinit();
458 close(bufmgr->auth_fd);
459 tbm_drm_helper_unset_tbm_master_fd();
461 tbm_drm_helper_unset_fd();
463 hal_tbm_put_backend(bufmgr->hal_backend);
464 bufmgr->hal_backend = NULL;
465 bufmgr->hal_bufmgr = NULL;
466 bufmgr->use_hal_tbm = 0;
468 if (bufmgr->backend_module_data) {
469 /* deinit and backend destroys the backend func and data */
470 bufmgr->backend_module_data->deinit(bufmgr->bufmgr_data);
471 bufmgr->bo_func = NULL;
472 bufmgr->bufmgr_func = NULL;
473 bufmgr->bufmgr_data = NULL;
474 bufmgr->backend_module_data = NULL;
476 /* destroy bufmgr priv */
477 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
478 bufmgr->backend->priv = NULL;
479 tbm_backend_free(bufmgr->backend);
480 bufmgr->backend = NULL;
483 dlclose(bufmgr->module_data);