1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, 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.h"
35 #include "tbm_bufmgr_int.h"
36 #include "tbm_bufmgr_backend.h"
37 #include "tbm_drm_helper.h"
40 #include <sys/resource.h>
51 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
52 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
53 static double scale_factor = 0;
54 void _tbm_bufmgr_mutex_unlock(void);
56 //#define TBM_BUFMGR_INIT_TIME
58 #define PREFIX_LIB "libtbm_"
59 #define SUFFIX_LIB ".so"
60 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
62 /* values to indicate unspecified fields in XF86ModReqInfo. */
63 #define MAJOR_UNSPEC 0xFF
64 #define MINOR_UNSPEC 0xFF
65 #define PATCH_UNSPEC 0xFFFF
66 #define ABI_VERS_UNSPEC 0xFFFFFFFF
68 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
69 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
70 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
71 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
72 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
74 #define MAX_SIZE_N(dest) (sizeof(dest) - strlen(dest) - 1)
77 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
79 TBM_ERR("'%s' failed.\n", #cond);\
80 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
81 _tbm_bufmgr_mutex_unlock();\
86 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
88 TBM_ERR("'%s' failed.\n", #cond);\
89 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
90 _tbm_bufmgr_mutex_unlock();\
98 _tbm_bufmgr_mutex_lock(void)
100 pthread_mutex_lock(&tbm_bufmgr_lock);
104 _tbm_bufmgr_mutex_unlock(void)
106 pthread_mutex_unlock(&tbm_bufmgr_lock);
110 _tbm_util_get_max_surface_size(int *w, int *h)
112 tbm_surface_info_s info;
113 tbm_surface_h surface = NULL;
119 if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
122 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
123 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
127 if (*h < info.height)
136 _tbm_util_get_appname_brief(char *brief)
140 char temp[255] = {0,};
141 char *saveptr = NULL;
143 token = strtok_r(brief, delim, &saveptr);
145 while (token != NULL) {
146 memset(temp, 0x00, 255 * sizeof(char));
147 strncpy(temp, token, 254 * sizeof(char));
148 token = strtok_r(NULL, delim, &saveptr);
151 snprintf(brief, sizeof(temp), "%s", temp);
155 _tbm_util_get_appname_from_pid(long pid, char *str)
157 char fn_cmdline[255] = {0, }, cmdline[255];
161 if (pid <= 0) return;
163 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
165 fp = fopen(fn_cmdline, "r");
167 TBM_ERR("cannot file open %s\n", fn_cmdline);
171 if (!fgets(cmdline, 255, fp)) {
172 TBM_ERR("fail to get appname for pid(%ld)\n", pid);
179 len = strlen(cmdline);
181 memset(cmdline, 0x00, 255);
185 snprintf(str, sizeof(cmdline), "%s", cmdline);
189 _tbm_backend_load_hal_tbm(tbm_bufmgr bufmgr)
191 hal_tbm_backend *hal_backend = NULL;
192 hal_tbm_bufmgr_capability capability;
193 hal_tbm_bufmgr *hal_bufmgr;
194 hal_tbm_error ret = HAL_TBM_ERROR_NONE;
195 hal_tbm_fd auth_drm_fd = -1;
197 hal_backend = hal_tbm_get_backend(&ret);
198 if (hal_backend == NULL || ret != HAL_TBM_ERROR_NONE) {
199 TBM_ERR("get backend fail");
203 hal_bufmgr = hal_tbm_backend_get_bufmgr(hal_backend, &ret);
204 if (hal_bufmgr == NULL || ret != HAL_TBM_ERROR_NONE) {
205 TBM_ERR("get hal_bufmgr fail");
206 goto get_backend_fail;
209 if (hal_tbm_backend_has_drm_device(hal_backend, &ret)) {
210 auth_drm_fd = hal_tbm_backend_get_master_drm_fd(hal_backend, &ret);
211 if (auth_drm_fd < 0) {
212 TBM_INFO("tbm_backend has no master drm_fd.");
214 auth_drm_fd = tbm_drm_helper_get_master_fd();
215 if (auth_drm_fd < 0) {
216 TBM_INFO("libtbm requests an authenticated drm_fd to a process(display server).");
217 if (!tbm_drm_helper_get_auth_info(&auth_drm_fd, NULL, NULL)) {
218 TBM_ERR("get auth drm_fd fail");
219 goto get_backend_fail;
222 TBM_INFO("libtbm gets a master drm_fd from libtdm via tbm_drm_helper.");
225 TBM_INFO("libtbm sends a master drm_fd as an authentiated drm_fd to tbm_backend.");
226 ret = hal_tbm_backend_set_authenticated_drm_fd(hal_backend, auth_drm_fd);
227 if (ret != HAL_TBM_ERROR_NONE) {
228 TBM_ERR("hal_tbm_backend_set_authenticated_drm_fd failed.");
229 goto get_backend_fail;
232 TBM_INFO("tbm_backend has a master drm_fd.");
234 tbm_drm_helper_set_tbm_master_fd(auth_drm_fd);
236 tbm_drm_helper_set_fd(auth_drm_fd);
239 capability = hal_tbm_bufmgr_get_capabilities(hal_bufmgr, &ret);
240 if (ret != HAL_TBM_ERROR_NONE) {
241 TBM_ERR("hal_tbm_bufmgr_get_capabilities fail.");
242 goto get_backend_fail;
245 if (capability == HAL_TBM_BUFMGR_CAPABILITY_NONE) {
246 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
247 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
248 goto get_backend_fail;
250 if (!(capability & HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
251 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
252 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
253 goto get_backend_fail;
255 bufmgr->capabilities = capability;
257 bufmgr->hal_backend = hal_backend;
258 bufmgr->hal_bufmgr = hal_bufmgr;
260 bufmgr->use_hal_tbm = 1;
262 TBM_INFO("use HAL-TBM_API");
267 if (auth_drm_fd >= 0)
269 hal_tbm_put_backend(hal_backend);
274 _check_version(TBMModuleVersionInfo *data)
276 int backend_module_major, backend_module_minor;
277 int tbm_backend_major, tbm_backend_minor;
279 backend_module_major = GET_ABI_MAJOR(data->abiversion);
280 backend_module_minor = GET_ABI_MINOR(data->abiversion);
282 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
283 data->modname ? data->modname : "UNKNOWN!",
284 data->vendor ? data->vendor : "UNKNOWN!", backend_module_major, backend_module_minor);
286 tbm_backend_major = GET_ABI_MAJOR(TBM_ABI_VERSION);
287 tbm_backend_minor = GET_ABI_MINOR(TBM_ABI_VERSION);
289 TBM_DBG("TBM ABI version %d.%d\n",
290 tbm_backend_major, tbm_backend_minor);
292 if (backend_module_major != tbm_backend_major) {
293 TBM_ERR("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
294 backend_module_major, tbm_backend_major);
296 } else if (backend_module_minor > tbm_backend_minor) {
297 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
298 backend_module_minor, tbm_backend_minor);
306 _tbm_backend_check_bufmgr_func(tbm_backend_bufmgr_func *bufmgr_func)
308 TBM_RETURN_VAL_IF_FAIL(bufmgr_func, 0); /* mandatory symbol */
309 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_capabilities, 0); /* mandatory symbol */
310 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_bind_native_display, 0); /* mandatory symbol */
311 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_supported_formats, 0); /* mandatory symbol */
312 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_get_plane_data, 0); /* mandatory symbol */
313 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_alloc_bo, 0); /* mandatory symbol */
314 if (!bufmgr_func->bufmgr_alloc_bo_with_format)
315 TBM_DBG("No bufmgr_func->bufmgr_alloc_bo_with_format.");
316 TBM_RETURN_VAL_IF_FAIL(bufmgr_func->bufmgr_import_fd, 0); /* mandatory symbol */
317 if (!bufmgr_func->bufmgr_import_key)
318 TBM_DBG("No bufmgr_func->bo_export_key.");
324 _tbm_backend_check_bufmgr_bo(tbm_backend_bo_func *bo_func)
326 TBM_RETURN_VAL_IF_FAIL(bo_func, 0); /* mandatory symbol */
327 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_free, 0); /* mandatory symbol */
328 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_size, 0); /* mandatory symbol */
329 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_memory_types, 0); /* mandatory symbol */
330 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_get_handle, 0); /* mandatory symbol */
331 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_map, 0); /* mandatory symbol */
332 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_unmap, 0); /* mandatory symbol */
333 if (!bo_func->bo_lock)
334 TBM_DBG("No bo_func->bo_lock.");
335 if (!bo_func->bo_unlock)
336 TBM_DBG("No bo_func->bo_unlock.");
337 TBM_RETURN_VAL_IF_FAIL(bo_func->bo_export_fd, 0); /* mandatory symbol */
338 if (!bo_func->bo_export_key)
339 TBM_INFO("No bo_func->bo_export_key.");
345 _tbm_backend_load_module(tbm_bufmgr bufmgr, const char *file)
347 char path[PATH_MAX] = {0, };
348 void *module_data = NULL;
349 tbm_backend_module *backend_module_data = NULL;
350 tbm_backend_bufmgr_data *bufmgr_data = NULL;
351 int backend_module_major, backend_module_minor;
352 int tbm_backend_major, tbm_backend_minor;
355 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
357 module_data = dlopen(path, RTLD_LAZY);
359 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
363 backend_module_data = dlsym(module_data, "tbm_backend_module_data");
364 if (!backend_module_data) {
365 TBM_ERR("Error: module does not have data object.\n");
369 tbm_backend_major = GET_ABI_MAJOR(TBM_BACKEND_ABI_LATEST_VERSION);
370 tbm_backend_minor = GET_ABI_MINOR(TBM_BACKEND_ABI_LATEST_VERSION);
371 TBM_INFO("TBM Backend ABI version %d.%d\n", tbm_backend_major, tbm_backend_minor);
373 backend_module_major = GET_ABI_MAJOR(backend_module_data->abi_version);
374 backend_module_minor = GET_ABI_MINOR(backend_module_data->abi_version);
376 TBM_INFO("TBM module %s: vendor=\"%s\" Backend ABI version=%d.%d\n",
377 backend_module_data->name ? backend_module_data->name : "UNKNOWN!",
378 backend_module_data->vendor ? backend_module_data->vendor : "UNKNOWN!",
379 backend_module_major, backend_module_minor);
381 if (backend_module_major > tbm_backend_major) {
382 TBM_ERR("TBM module ABI major ver(%d) is newer than the TBM's ver(%d)\n",
383 backend_module_major, tbm_backend_major);
385 } else if (backend_module_minor > tbm_backend_minor) {
386 TBM_ERR("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
387 backend_module_minor, tbm_backend_minor);
391 if (!backend_module_data->init) {
392 TBM_ERR("Error: module does not supply init symbol.\n");
396 if (!backend_module_data->deinit) {
397 TBM_ERR("Error: module does not supply deinit symbol.\n");
401 bufmgr_data = backend_module_data->init(bufmgr, &error);
403 TBM_ERR("Fail to init module(%s)\n", file);
407 /* check the mandatory symbols of the backend module */
408 if (!_tbm_backend_check_bufmgr_func(bufmgr->bufmgr_func)) {
409 TBM_ERR("Fail to check the bufmgr_func symboles.");
413 if (!_tbm_backend_check_bufmgr_bo(bufmgr->bo_func)) {
414 TBM_ERR("Fail to check the bufmgr_bo symboles.");
418 /* get the capability */
419 bufmgr->capabilities = bufmgr->bufmgr_func->bufmgr_get_capabilities(bufmgr_data, &error);
420 if (bufmgr->capabilities == TBM_BUFMGR_CAPABILITY_NONE) {
421 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
422 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
426 if (!(bufmgr->capabilities & TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
427 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
428 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
432 bufmgr->module_data = module_data;
433 bufmgr->backend_module_data = backend_module_data;
434 bufmgr->bufmgr_data = bufmgr_data;
436 TBM_INFO("Success to load module(%s)\n", file);
442 bufmgr->backend_module_data->deinit(bufmgr_data);
444 dlclose(module_data);
450 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
452 char path[PATH_MAX] = {0, };
453 TBMModuleVersionInfo *vers;
454 TBMModuleData *initdata;
458 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
460 module_data = dlopen(path, RTLD_LAZY);
462 TBM_ERR("failed to load module: %s(%s)\n", dlerror(), file);
466 initdata = dlsym(module_data, "tbmModuleData");
468 TBM_ERR("Error: module does not have data object.\n");
472 vers = initdata->vers;
474 TBM_ERR("Error: module does not supply version information.\n");
478 init = initdata->init;
480 TBM_ERR("Error: module does not supply init symbol.\n");
484 if (!_check_version(vers)) {
485 TBM_ERR("Fail to check version.\n");
489 if (!init(bufmgr, fd)) {
490 TBM_ERR("Fail to init module(%s)\n", file);
494 if (!bufmgr->backend || !bufmgr->backend->priv) {
495 TBM_ERR("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
499 bufmgr->module_data = module_data;
501 TBM_DBG("Success to load module(%s)\n", file);
506 dlclose(module_data);
511 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
513 struct dirent **namelist;
516 /* try to load the hal-tbm backend module */
517 ret = _tbm_backend_load_hal_tbm(bufmgr);
521 /* try to load the new backend module */
522 ret = _tbm_backend_load_module(bufmgr, DEFAULT_LIB);
526 /* try to load the old(deprecated) backend mdoule */
527 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
531 /* load bufmgr priv from configured path */
532 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
534 TBM_ERR("no files : %s\n", BUFMGR_MODULE_DIR);
539 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
540 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
542 if (p && !strcmp(p, SUFFIX_LIB)) {
543 ret = _tbm_backend_load_module(bufmgr, namelist[n]->d_name);
545 ret = _tbm_bufmgr_load_module(bufmgr, fd,
546 namelist[n]->d_name);
560 _tbm_bufmgr_init(int fd, int server)
562 #ifdef TBM_BUFMGR_INIT_TIME
563 struct timeval start_tv, end_tv;
567 #ifdef TBM_BUFMGR_INIT_TIME
568 /* get the start tv */
569 gettimeofday(&start_tv, NULL);
574 /* LCOV_EXCL_START */
576 env = getenv("TBM_TRACE");
578 trace_mask = atoi(env);
579 TBM_DBG("TBM_TRACE=%s\n", env);
584 pthread_mutex_lock(&gLock);
586 _tbm_set_last_result(TBM_ERROR_NONE);
589 TBM_WRN("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
590 TBM_WRN("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
594 /* initialize buffer manager */
596 gBufMgr->ref_count++;
597 TBM_DBG("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
598 pthread_mutex_unlock(&gLock);
602 TBM_DBG("bufmgr init\n");
604 /* allocate bufmgr */
605 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
607 TBM_ERR("error: fail to alloc bufmgr fd(%d)\n", fd);
608 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
609 pthread_mutex_unlock(&gLock);
615 /* set the display_server flag before loading the backend module */
617 TBM_INFO("The tbm_bufmgr(%p) is used by display server. Need to bind the native_display.\n", gBufMgr);
618 gBufMgr->display_server = 1;
621 /* load bufmgr priv from env */
622 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
623 TBM_ERR("error : Fail to load bufmgr backend\n");
624 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
627 pthread_mutex_unlock(&gLock);
633 gBufMgr->ref_count = 1;
635 TBM_INFO("create tizen bufmgr:%p ref_count:%d\n",
636 gBufMgr, gBufMgr->ref_count);
638 /* setup the bo_lock_type */
639 env = getenv("BUFMGR_LOCK_TYPE");
640 if (env && !strcmp(env, "always"))
641 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
642 else if (env && !strcmp(env, "none"))
643 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_NEVER;
644 else if (env && !strcmp(env, "once"))
645 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ONCE;
647 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
649 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
651 /* intialize bo_list */
652 LIST_INITHEAD(&gBufMgr->bo_list);
654 /* intialize surf_list */
655 LIST_INITHEAD(&gBufMgr->surf_list);
657 /* intialize surf_queue_list */
658 LIST_INITHEAD(&gBufMgr->surf_queue_list);
660 /* intialize debug_key_list */
661 LIST_INITHEAD(&gBufMgr->debug_key_list);
663 #ifdef TBM_BUFMGR_INIT_TIME
665 gettimeofday(&end_tv, NULL);
666 TBM_INFO("tbm_bufmgr_init time: %ld ms", ((end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
669 pthread_mutex_unlock(&gLock);
675 tbm_bufmgr_init(int fd)
679 bufmgr = _tbm_bufmgr_init(fd, 0);
685 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
687 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
689 _tbm_bufmgr_mutex_lock();
690 pthread_mutex_lock(&gLock);
691 _tbm_set_last_result(TBM_ERROR_NONE);
694 TBM_ERR("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
695 pthread_mutex_unlock(&gLock);
696 _tbm_bufmgr_mutex_unlock();
701 if (bufmgr->ref_count > 0) {
702 TBM_DBG("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
703 pthread_mutex_unlock(&gLock);
704 _tbm_bufmgr_mutex_unlock();
708 /* destroy bo_list */
709 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
710 tbm_bo bo = NULL, tmp;
712 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
713 TBM_ERR("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
716 LIST_DELINIT(&bufmgr->bo_list);
719 /* destroy surf_list */
720 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
721 tbm_surface_h surf = NULL, tmp;
723 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
724 TBM_ERR("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
725 tbm_surface_destroy(surf);
727 LIST_DELINIT(&bufmgr->surf_list);
730 if (bufmgr->use_hal_tbm) {
731 if (bufmgr->auth_wl_socket_created) {
732 tbm_drm_helper_wl_auth_server_deinit();
733 close(bufmgr->auth_fd);
734 tbm_drm_helper_unset_tbm_master_fd();
736 tbm_drm_helper_unset_fd();
738 hal_tbm_put_backend(bufmgr->hal_backend);
739 bufmgr->hal_backend = NULL;
740 bufmgr->hal_bufmgr = NULL;
741 bufmgr->use_hal_tbm = 0;
743 if (bufmgr->backend_module_data) {
744 /* deinit and backend destroys the backend func and data */
745 bufmgr->backend_module_data->deinit(bufmgr->bufmgr_data);
746 bufmgr->bo_func = NULL;
747 bufmgr->bufmgr_func = NULL;
748 bufmgr->bufmgr_data = NULL;
749 bufmgr->backend_module_data = NULL;
751 /* destroy bufmgr priv */
752 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
753 bufmgr->backend->priv = NULL;
754 tbm_backend_free(bufmgr->backend);
755 bufmgr->backend = NULL;
758 dlclose(bufmgr->module_data);
763 TBM_INFO("destroy tbm_bufmgr(%p)\n", bufmgr);
768 pthread_mutex_unlock(&gLock);
769 _tbm_bufmgr_mutex_unlock();
773 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
775 unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
777 _tbm_bufmgr_mutex_lock();
778 _tbm_set_last_result(TBM_ERROR_NONE);
780 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
781 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
783 capabilities = bufmgr->capabilities;
785 _tbm_bufmgr_mutex_unlock();
790 /* LCOV_EXCL_START */
792 tbm_bufmgr_debug_tbm_info_get(tbm_bufmgr bufmgr)
794 char app_name[255] = {0,}, title[512] = {0,};
795 tbm_surface_debug_data *debug_old_data = NULL;
803 pthread_mutex_lock(&gLock);
804 _tbm_set_last_result(TBM_ERROR_NONE);
806 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
807 TBM_ERR("invalid bufmgr\n");
808 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
809 pthread_mutex_unlock(&gLock);
815 TBM_ERR("Fail to allocate the string.\n");
816 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
817 pthread_mutex_unlock(&gLock);
821 TBM_SNRPRINTF(str, len, c, "\n");
822 pid = syscall(SYS_getpid);
823 _tbm_util_get_appname_from_pid(pid, app_name);
824 _tbm_util_get_appname_brief(app_name);
825 TBM_SNRPRINTF(str, len, c, "===========================================TBM DEBUG: %s(%ld)===========================================\n",
828 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
830 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
831 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
832 strncat(title, " ", MAX_SIZE_N(title));
833 strncat(title, debug_old_data->key, MAX_SIZE_N(title));
837 TBM_SNRPRINTF(str, len, c, "[tbm_surface information]\n");
838 TBM_SNRPRINTF(str, len, c, "%s\n", title);
840 /* show the tbm_surface information in surf_list */
841 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
842 tbm_surface_h surf = NULL;
845 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
846 char data[512] = {0,};
847 unsigned int surf_pid = 0;
850 surf_pid = _tbm_surface_internal_get_debug_pid(surf);
852 /* if pid is null, set the self_pid */
853 surf_pid = syscall(SYS_getpid);;
856 memset(app_name, 0x0, 255 * sizeof(char));
857 if (geteuid() == 0) {
858 _tbm_util_get_appname_from_pid(surf_pid, app_name);
859 _tbm_util_get_appname_brief(app_name);
861 snprintf(app_name, sizeof(app_name), "%d", surf_pid);
864 snprintf(data, 255, "%-3d %-11p %-5d %-6u %-7u %-4u %-7u %-3d %-3d %-8d %-9s %-22s",
871 surf->info.size / 1024,
875 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
878 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
879 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
882 strncat(data, " ", MAX_SIZE_N(title));
884 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
886 strncat(data, value, MAX_SIZE_N(title));
888 strncat(data, "none", MAX_SIZE_N(title));
891 TBM_SNRPRINTF(str, len, c, "%s\n", data);
893 for (i = 0; i < surf->num_bos; i++) {
894 if (bufmgr->use_hal_tbm) {
895 size = hal_tbm_bo_get_size((hal_tbm_bo *)surf->bos[i]->bo_data, (hal_tbm_error *)&error);
896 if (error != TBM_ERROR_NONE)
897 TBM_WRN("fail to get the size of bo.");
898 } else if (bufmgr->backend_module_data) {
899 size = bufmgr->bo_func->bo_get_size(surf->bos[i]->bo_data, &error);
900 if (error != TBM_ERROR_NONE)
901 TBM_WRN("fail to get the size of bo.");
903 size = bufmgr->backend->bo_size(surf->bos[i]);
904 TBM_SNRPRINTF(str, len, c, " bo:%-12p %-26d%-10d\n",
906 surf->bos[i]->ref_cnt,
911 TBM_SNRPRINTF(str, len, c, " no tbm_surfaces.\n");
912 TBM_SNRPRINTF(str, len, c, "\n");
914 TBM_SNRPRINTF(str, len, c, "[tbm_bo information]\n");
915 TBM_SNRPRINTF(str, len, c, "no bo refcnt size lock_cnt map_cnt flags surface name\n");
917 /* show the tbm_bo information in bo_list */
918 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
923 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
924 if (bo->bufmgr->use_hal_tbm) {
925 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
926 if (error != TBM_ERROR_NONE)
927 TBM_WRN("fail to get the size of bo.");
928 key = (tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
929 } else if (bufmgr->backend_module_data) {
930 size = bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
931 if (error != TBM_ERROR_NONE)
932 TBM_WRN("fail to get the size of bo.");
933 key = bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
934 if (error != TBM_ERROR_NONE)
935 TBM_WRN("fail to get the tdm_key of bo.");
937 size = bufmgr->backend->bo_size(bo);
938 key = bufmgr->backend->bo_export(bo);
940 TBM_SNRPRINTF(str, len, c, "%-3d %-11p %-5d %-7d %-6d %-5u %-7d %-11p %-4d\n",
952 TBM_SNRPRINTF(str, len, c, "no tbm_bos.\n");
953 TBM_SNRPRINTF(str, len, c, "\n");
955 TBM_SNRPRINTF(str, len, c, "========================================================================================================\n");
957 pthread_mutex_unlock(&gLock);
963 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
966 str = tbm_bufmgr_debug_tbm_info_get(bufmgr);
974 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
976 _tbm_bufmgr_mutex_lock();
977 _tbm_set_last_result(TBM_ERROR_NONE);
979 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
980 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
983 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
987 _tbm_bufmgr_mutex_unlock();
991 tbm_bufmgr_debug_set_trace_mask(tbm_bufmgr bufmgr, tbm_bufmgr_debug_trace_mask mask, int set)
993 _tbm_bufmgr_mutex_lock();
994 _tbm_set_last_result(TBM_ERROR_NONE);
996 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
997 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1002 TBM_INFO("bufmgr=%p sets the trace_mask=%d\n", bufmgr, mask);
1003 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
1004 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_BO");
1005 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
1006 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
1007 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
1008 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE");
1009 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
1010 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
1011 } else if (set == 0) {
1012 trace_mask &= ~mask;
1014 TBM_INFO("bufmgr=%p unsets the trace_mask=%d\n", bufmgr, mask);
1015 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
1016 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_BO");
1017 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
1018 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
1019 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
1020 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE");
1021 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
1022 TBM_INFO(" TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
1024 TBM_WRN("set value is wrong.(set=%d)", set);
1027 _tbm_bufmgr_mutex_unlock();
1031 tbm_bufmgr_debug_dump_set_scale(double scale)
1033 pthread_mutex_lock(&gLock);
1034 _tbm_set_last_result(TBM_ERROR_NONE);
1035 scale_factor = scale;
1036 pthread_mutex_unlock(&gLock);
1040 tbm_bufmgr_debug_get_ref_count(void)
1044 pthread_mutex_lock(&gLock);
1046 _tbm_set_last_result(TBM_ERROR_NONE);
1048 refcnt = (gBufMgr) ? gBufMgr->ref_count : 0;
1050 pthread_mutex_unlock(&gLock);
1056 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1058 pthread_mutex_lock(&gLock);
1059 _tbm_set_last_result(TBM_ERROR_NONE);
1062 TBM_DBG("count=%d onoff=%d\n", count, onoff);
1064 tbm_surface_internal_dump_end();
1069 TBM_ERR("path is null");
1070 pthread_mutex_unlock(&gLock);
1073 TBM_DBG("path=%s count=%d onoff=%d\n", path, count, onoff);
1075 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1076 TBM_ERR("Fail to get tbm_surface size.\n");
1077 pthread_mutex_unlock(&gLock);
1081 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
1087 pthread_mutex_unlock(&gLock);
1093 tbm_bufmgr_debug_dump_all(char *path)
1095 int w, h, count = 0;
1096 tbm_surface_h surface = NULL;
1098 pthread_mutex_lock(&gLock);
1099 _tbm_set_last_result(TBM_ERROR_NONE);
1102 TBM_ERR("path is null.\n");
1103 pthread_mutex_unlock(&gLock);
1107 TBM_DBG("path=%s\n", path);
1109 count = _tbm_util_get_max_surface_size(&w, &h);
1111 TBM_ERR("No tbm_surface.\n");
1112 pthread_mutex_unlock(&gLock);
1116 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
1119 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
1120 tbm_surface_internal_dump_buffer(surface, "dump_all");
1122 tbm_surface_internal_dump_end();
1124 pthread_mutex_unlock(&gLock);
1129 /* internal function */
1131 _tbm_bufmgr_get_bufmgr(void)
1137 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
1142 _tbm_bufmgr_mutex_lock();
1143 _tbm_set_last_result(TBM_ERROR_NONE);
1145 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1147 if (bufmgr->use_hal_tbm) {
1148 if (hal_tbm_backend_has_drm_device(bufmgr->hal_backend, &ret)) {
1149 int fd = tbm_drm_helper_get_fd(); // this must be the auth drm_fd.(master drm_fd);
1151 TBM_ERR("error: tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
1152 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1153 _tbm_bufmgr_mutex_unlock();
1157 // make the wayland server socket for sending the authenticated drm_fd to wayland clients.
1158 if (!tbm_drm_helper_wl_auth_server_init(native_display, fd, NULL, 0)) {
1159 TBM_ERR("error: tbm_drm_helper_wl_auth_server_init failed\n", bufmgr, native_display);
1161 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1162 _tbm_bufmgr_mutex_unlock();
1165 TBM_INFO("tbm creates a wayland socket for authentication of drm_fd.");
1167 bufmgr->auth_wl_socket_created = 1;
1168 bufmgr->auth_fd = fd;
1170 } else if (bufmgr->backend_module_data) {
1171 if (!bufmgr->bufmgr_func->bufmgr_bind_native_display) {
1172 TBM_WRN("skip: tbm_bufmgr(%p) native_display(%p)\n",
1173 bufmgr, native_display);
1174 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1175 _tbm_bufmgr_mutex_unlock();
1179 error = bufmgr->bufmgr_func->bufmgr_bind_native_display(bufmgr->bufmgr_data, (tbm_native_display *)native_display);
1180 if (error != TBM_ERROR_NONE) {
1181 TBM_ERR("error: tbm_bufmgr(%p) native_display(%p) error(%d)\n",
1182 bufmgr, native_display, error);
1183 _tbm_set_last_result(error);
1184 _tbm_bufmgr_mutex_unlock();
1189 if (!bufmgr->backend->bufmgr_bind_native_display) {
1190 TBM_WRN("skip: tbm_bufmgr(%p) native_display(%p)\n",
1191 bufmgr, native_display);
1192 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1193 _tbm_bufmgr_mutex_unlock();
1197 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, native_display);
1199 TBM_ERR("error: tbm_bufmgr(%p) native_display(%p)\n",
1200 bufmgr, native_display);
1201 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1202 _tbm_bufmgr_mutex_unlock();
1207 TBM_INFO("tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
1209 _tbm_bufmgr_mutex_unlock();
1215 tbm_bufmgr_server_init(void)
1219 bufmgr = _tbm_bufmgr_init(-1, 1);
1225 tbm_bufmgr_set_bo_lock_type(tbm_bufmgr bufmgr, tbm_bufmgr_bo_lock_type bo_lock_type)
1227 _tbm_bufmgr_mutex_lock();
1228 _tbm_set_last_result(TBM_ERROR_NONE);
1230 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1231 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, 0);
1233 pthread_mutex_lock(&gLock);
1234 gBufMgr->bo_lock_type = bo_lock_type;
1235 pthread_mutex_unlock(&gLock);
1237 TBM_INFO("The bo_lock_type of the bo is %d\n", bo_lock_type);
1239 _tbm_bufmgr_mutex_unlock();
1245 int tbm_bufmgr_get_fd_limit(void)
1249 if (getrlimit(RLIMIT_NOFILE, &lim))
1252 return (int)lim.rlim_cur;
1255 tbm_bufmgr tbm_bufmgr_get(void)
1259 /* LCOV_EXCL_STOP */