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_module *module)
59 hal_tbm_backend *hal_backend = NULL;
60 hal_tbm_bufmgr *hal_bufmgr;
61 hal_tbm_error ret = HAL_TBM_ERROR_NONE;
62 hal_tbm_fd auth_drm_fd = -1;
64 hal_backend = hal_tbm_get_backend(&ret);
65 if (hal_backend == NULL || ret != HAL_TBM_ERROR_NONE) {
66 TBM_ERR("get backend fail");
70 hal_bufmgr = hal_tbm_backend_get_bufmgr(hal_backend, &ret);
71 if (hal_bufmgr == NULL || ret != HAL_TBM_ERROR_NONE) {
72 TBM_ERR("get hal_bufmgr fail");
73 goto get_backend_fail;
76 if (hal_tbm_backend_has_drm_device(hal_backend, &ret)) {
77 auth_drm_fd = hal_tbm_backend_get_master_drm_fd(hal_backend, &ret);
78 if (auth_drm_fd < 0) {
79 TBM_INFO("tbm_backend has no master drm_fd.");
81 auth_drm_fd = tbm_drm_helper_get_master_fd();
82 if (auth_drm_fd < 0) {
83 TBM_INFO("libtbm requests an authenticated drm_fd to a process(display server).");
84 if (!tbm_drm_helper_get_auth_info(&auth_drm_fd, NULL, NULL)) {
85 TBM_ERR("get auth drm_fd fail");
86 goto get_backend_fail;
89 TBM_INFO("libtbm gets a master drm_fd from libtdm via tbm_drm_helper.");
92 TBM_INFO("libtbm sends a master drm_fd as an authentiated drm_fd to tbm_backend.");
93 ret = hal_tbm_backend_set_authenticated_drm_fd(hal_backend, auth_drm_fd);
94 if (ret != HAL_TBM_ERROR_NONE) {
95 TBM_ERR("hal_tbm_backend_set_authenticated_drm_fd failed.");
96 goto get_backend_fail;
99 TBM_INFO("tbm_backend has a master drm_fd.");
101 tbm_drm_helper_set_tbm_master_fd(auth_drm_fd);
103 tbm_drm_helper_set_fd(auth_drm_fd);
106 module->hal_backend = hal_backend;
107 module->hal_bufmgr = hal_bufmgr;
109 module->use_hal_tbm = 1;
111 TBM_INFO("use HAL-TBM_API");
116 if (auth_drm_fd >= 0)
118 hal_tbm_put_backend(hal_backend);
123 _check_version(TBMModuleVersionInfo *data)
125 int backend_module_major, backend_module_minor;
126 int tbm_backend_major, tbm_backend_minor;
128 backend_module_major = GET_ABI_MAJOR(data->abiversion);
129 backend_module_minor = GET_ABI_MINOR(data->abiversion);
131 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
132 data->modname ? data->modname : "UNKNOWN!",
133 data->vendor ? data->vendor : "UNKNOWN!", backend_module_major, backend_module_minor);
135 tbm_backend_major = GET_ABI_MAJOR(TBM_ABI_VERSION);
136 tbm_backend_minor = GET_ABI_MINOR(TBM_ABI_VERSION);
138 TBM_DBG("TBM ABI version %d.%d\n",
139 tbm_backend_major, tbm_backend_minor);
141 if (backend_module_major != tbm_backend_major) {
142 TBM_ERR("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
143 backend_module_major, tbm_backend_major);
145 } else if (backend_module_minor > tbm_backend_minor) {
146 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
147 backend_module_minor, tbm_backend_minor);
155 _tbm_backend_check_bufmgr_func(tbm_backend_bufmgr_func *bufmgr_func)
157 TBM_RETURN_VAL_IF_FAIL(bufmgr_func, 0); /* mandatory symbol */
158 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0); /* mandatory symbol */
159 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_bind_native_display, 0); /* mandatory symbol */
160 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_supported_formats, 0); /* mandatory symbol */
161 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_plane_data, 0); /* mandatory symbol */
162 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, 0); /* mandatory symbol */
163 if (!bufmgr_func->bufmgr_alloc_bo_with_format)
164 TBM_DBG("No bufmgr_func->bufmgr_alloc_bo_with_format.");
165 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_import_fd, 0); /* mandatory symbol */
166 if (!bufmgr_func->bufmgr_import_key)
167 TBM_DBG("No bufmgr_func->bo_export_key.");
173 _tbm_backend_check_bufmgr_bo(tbm_backend_bo_func *bo_func)
175 TBM_RETURN_VAL_IF_FAIL(bo_func, 0); /* mandatory symbol */
176 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_free, 0); /* mandatory symbol */
177 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_size, 0); /* mandatory symbol */
178 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_memory_types, 0); /* mandatory symbol */
179 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_handle, 0); /* mandatory symbol */
180 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_map, 0); /* mandatory symbol */
181 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_unmap, 0); /* mandatory symbol */
182 if (!bo_func->bo_lock)
183 TBM_DBG("No bo_func->bo_lock.");
184 if (!bo_func->bo_unlock)
185 TBM_DBG("No bo_func->bo_unlock.");
186 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_export_fd, 0); /* mandatory symbol */
187 if (!bo_func->bo_export_key)
188 TBM_INFO("No bo_func->bo_export_key.");
194 _tbm_backend_load_module(tbm_module *module, const char *file)
196 char path[PATH_MAX] = {0, };
197 void *module_data = NULL;
198 tbm_backend_module *backend_module_data = NULL;
199 tbm_backend_bufmgr_data *bufmgr_data = NULL;
200 int backend_module_major, backend_module_minor;
201 int tbm_backend_major, tbm_backend_minor;
204 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
206 module_data = dlopen(path, RTLD_LAZY);
208 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
212 backend_module_data = dlsym(module_data, "tbm_backend_module_data");
213 if (!backend_module_data) {
214 TBM_ERR("Error: module does not have data object.\n");
218 tbm_backend_major = GET_ABI_MAJOR(TBM_BACKEND_ABI_LATEST_VERSION);
219 tbm_backend_minor = GET_ABI_MINOR(TBM_BACKEND_ABI_LATEST_VERSION);
220 TBM_INFO("TBM Backend ABI version %d.%d\n", tbm_backend_major, tbm_backend_minor);
222 backend_module_major = GET_ABI_MAJOR(backend_module_data->abi_version);
223 backend_module_minor = GET_ABI_MINOR(backend_module_data->abi_version);
225 TBM_INFO("TBM module %s: vendor=\"%s\" Backend ABI version=%d.%d\n",
226 backend_module_data->name ? backend_module_data->name : "UNKNOWN!",
227 backend_module_data->vendor ? backend_module_data->vendor : "UNKNOWN!",
228 backend_module_major, backend_module_minor);
230 if (backend_module_major > tbm_backend_major) {
231 TBM_ERR("TBM module ABI major ver(%d) is newer than the TBM's ver(%d)\n",
232 backend_module_major, tbm_backend_major);
234 } else if (backend_module_minor > tbm_backend_minor) {
235 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
236 backend_module_minor, tbm_backend_minor);
240 if (!backend_module_data->init) {
241 TBM_ERR("Error: module does not supply init symbol.\n");
245 if (!backend_module_data->deinit) {
246 TBM_ERR("Error: module does not supply deinit symbol.\n");
250 bufmgr_data = backend_module_data->init((tbm_bufmgr)module, &error);
252 TBM_ERR("Fail to init module(%s)\n", file);
256 /* check the mandatory symbols of the backend module */
257 if (!_tbm_backend_check_bufmgr_func(module->bufmgr_func)) {
258 TBM_ERR("Fail to check the bufmgr_func symboles.");
262 if (!_tbm_backend_check_bufmgr_bo(module->bo_func)) {
263 TBM_ERR("Fail to check the bufmgr_bo symboles.");
267 module->module_data = module_data;
268 module->backend_module_data = backend_module_data;
269 module->bufmgr_data = bufmgr_data;
271 TBM_INFO("Success to load module(%s)\n", file);
277 module->backend_module_data->deinit(bufmgr_data);
279 dlclose(module_data);
285 _tbm_backend_load_bufmgr_module(tbm_module *module, int fd, const char *file)
287 char path[PATH_MAX] = {0, };
288 TBMModuleVersionInfo *vers;
289 TBMModuleData *initdata;
293 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
295 module_data = dlopen(path, RTLD_LAZY);
297 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
301 initdata = dlsym(module_data, "tbmModuleData");
303 TBM_ERR("Error: module does not have data object.\n");
307 vers = initdata->vers;
309 TBM_ERR("Error: module does not supply version information.\n");
313 init = initdata->init;
315 TBM_ERR("Error: module does not supply init symbol.\n");
319 if (!_check_version(vers)) {
320 TBM_ERR("Fail to check version.\n");
324 if (!init((tbm_bufmgr)module, fd)) {
325 TBM_ERR("Fail to init module(%s)\n", file);
329 if (!module->backend || !module->backend->priv) {
330 TBM_ERR("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
334 module->module_data = module_data;
336 TBM_DBG("Success to load module(%s)\n", file);
341 dlclose(module_data);
348 tbm_module_load(int fd)
351 struct dirent **namelist;
354 module = calloc(1, sizeof(struct _tbm_module));
356 TBM_ERR("fail to allocate the memory");
360 /* try to load the hal-tbm backend module */
361 ret = _tbm_backend_load_hal_tbm(module);
363 module->type = TBM_MODULE_TYPE_HAL_TBM;
367 /* try to load the new backend module */
368 ret = _tbm_backend_load_module(module, DEFAULT_LIB);
370 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
374 /* try to load the old(deprecated) backend mdoule */
375 ret = _tbm_backend_load_bufmgr_module(module, fd, DEFAULT_LIB);
377 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
381 /* load backend_module from configured path */
382 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
384 TBM_ERR("no files : %s\n", BUFMGR_MODULE_DIR);
385 tbm_module_unload(module);
390 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
391 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
393 if (p && !strcmp(p, SUFFIX_LIB)) {
394 ret = _tbm_backend_load_module(module, namelist[n]->d_name);
396 module->type = TBM_MODULE_TYPE_TBM_BACKEND;
398 ret = _tbm_backend_load_bufmgr_module(module, fd, namelist[n]->d_name);
399 module->type = TBM_MODULE_TYPE_BUFMGR_BACKEND;
419 tbm_module_unload(tbm_module *module)
421 switch (module->type) {
422 case TBM_MODULE_TYPE_HAL_TBM:
423 if (module->auth_wl_socket_created) {
424 tbm_drm_helper_wl_auth_server_deinit();
425 close(module->auth_fd);
427 tbm_drm_helper_unset_tbm_master_fd();
428 tbm_drm_helper_unset_fd();
430 hal_tbm_put_backend(module->hal_backend);
431 module->hal_backend = NULL;
432 module->hal_bufmgr = NULL;
433 module->use_hal_tbm = 0;
435 case TBM_MODULE_TYPE_TBM_BACKEND:
436 module->backend_module_data->deinit(module->bufmgr_data);
437 module->bo_func = NULL;
438 module->bufmgr_func = NULL;
439 module->bufmgr_data = NULL;
440 module->backend_module_data = NULL;
442 dlclose(module->module_data);
444 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
445 module->backend->bufmgr_deinit(module->backend->priv);
446 module->backend->priv = NULL;
447 tbm_backend_free(module->backend);
448 module->backend = NULL;
450 dlclose(module->module_data);
453 TBM_ERR("Wrong module type:%d", module->type);
461 tbm_module_bufmgr_get_capabilities(tbm_module *module, tbm_error_e *error)
463 int capabilities = 0;
464 tbm_backend_bufmgr_func *bufmgr_func = NULL;
466 TBM_RETURN_VAL_SET_ERR_IF_FAIL(module, TBM_BUFMGR_CAPABILITY_NONE, *error, TBM_ERROR_INVALID_PARAMETER);
468 switch (module->type) {
469 case TBM_MODULE_TYPE_HAL_TBM:
470 capabilities = hal_tbm_bufmgr_get_capabilities(module->hal_bufmgr, (hal_tbm_error *)error);
472 case TBM_MODULE_TYPE_TBM_BACKEND:
473 bufmgr_func = module->bufmgr_func;
474 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func, 0, *error, TBM_ERROR_INVALID_OPERATION);
475 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0, *error, TBM_ERROR_NOT_SUPPORTED);
477 capabilities = module->bufmgr_func->bufmgr_get_capabilities(module->bufmgr_data, error);
479 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
480 TBM_WRN("!!WARNING: This backend interface will be DEPRECATED after Tizen 7.0.");
481 TBM_ERR("Do not support at tbm_bufmgr_backend.");
483 *error = TBM_ERROR_NOT_SUPPORTED;
486 TBM_ERR("Wrong module type:%d", module->type);
487 *error = TBM_ERROR_INVALID_OPERATION;
494 tbm_backend_bo_data *
495 tbm_module_bufmgr_bo_alloc(tbm_module *module, tbm_bo bo, int size, int flags, tbm_error_e *error)
497 tbm_backend_bo_data *bo_data = NULL;
498 tbm_backend_bufmgr_func *bufmgr_func = NULL;
499 tbm_bufmgr_backend backend = NULL;
501 TBM_RETURN_VAL_SET_ERR_IF_FAIL(module, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
503 switch (module->type) {
504 case TBM_MODULE_TYPE_HAL_TBM:
505 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo(module->hal_bufmgr, size, flags, (hal_tbm_error *)error);
507 case TBM_MODULE_TYPE_TBM_BACKEND:
508 bufmgr_func = module->bufmgr_func;
509 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func, NULL, *error, TBM_ERROR_INVALID_OPERATION);
510 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
512 bo_data = module->bufmgr_func->bufmgr_alloc_bo(module->bufmgr_data, (unsigned int)size, flags, error);
514 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
515 TBM_WRN("!!WARNING: This backend interface will be DEPRECATED after Tizen 7.0.");
516 backend = module->backend;
517 TBM_RETURN_VAL_SET_ERR_IF_FAIL(backend, NULL, *error, TBM_ERROR_INVALID_OPERATION);
518 TBM_RETURN_VAL_SET_ERR_IF_FAIL(backend->bo_alloc, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
520 bo_data = (void *)module->backend->bo_alloc(bo, size, flags);
521 *error = TBM_ERROR_NONE;
524 TBM_ERR("Wrong module type:%d", module->type);
525 *error = TBM_ERROR_INVALID_OPERATION;
532 tbm_backend_bo_data *
533 tbm_module_bufmgr_bo_alloc_with_format(tbm_module *module, int format, int bo_idx, int width,
534 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
536 tbm_backend_bo_data *bo_data = NULL;
537 tbm_backend_bufmgr_func *bufmgr_func = NULL;
539 TBM_RETURN_VAL_SET_ERR_IF_FAIL(module, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
541 switch (module->type) {
542 case TBM_MODULE_TYPE_HAL_TBM:
543 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(module->hal_bufmgr,
544 format, bo_idx, width, height, bpp,
545 (hal_tbm_bo_memory_type)flags, (hal_tbm_error *)error);
547 case TBM_MODULE_TYPE_TBM_BACKEND:
548 bufmgr_func = module->bufmgr_func;
549 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func, NULL, *error, TBM_ERROR_INVALID_OPERATION);
550 TBM_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr_func->bufmgr_alloc_bo_with_format, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
552 bo_data = bufmgr_func->bufmgr_alloc_bo_with_format(module->bufmgr_data, format, bo_idx, width, height, flags, error);
554 case TBM_MODULE_TYPE_BUFMGR_BACKEND:
555 TBM_WRN("!!WARNING: This backend interface will be DEPRECATED after Tizen 7.0.");
556 TBM_ERR("error: not supported tbm_bo_alloc_with_format.");
558 *error = TBM_ERROR_NOT_SUPPORTED;
561 TBM_ERR("Wrong module type:%d", module->type);
562 *error = TBM_ERROR_INVALID_OPERATION;