+static void *
+tbm_sprd_bo_import_fd (tbm_bo bo, tbm_fd key)
+{
+ SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
+
+ tbm_bufmgr_sprd bufmgr_sprd;
+ tbm_bo_sprd bo_sprd;
+
+ bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
+ SPRD_RETURN_VAL_IF_FAIL (bufmgr_sprd!=NULL, 0);
+
+ unsigned int gem = 0;
+ unsigned int real_size = -1;
+ struct drm_sprd_gem_info info = {0, };
+
+ //getting handle from fd
+ struct drm_prime_handle arg = {0, };
+
+ arg.fd = key;
+ arg.flags = 0;
+ if (drmIoctl (bufmgr_sprd->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg))
+ {
+ TBM_SPRD_LOG ("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
+ bo, arg.fd, strerror(errno));
+ return NULL;
+ }
+ gem = arg.handle;
+
+ /* Determine size of bo. The fd-to-handle ioctl really should
+ * return the size, but it doesn't. If we have kernel 3.12 or
+ * later, we can lseek on the prime fd to get the size. Older
+ * kernels will just fail, in which case we fall back to the
+ * provided (estimated or guess size). */
+ real_size = lseek(key, 0, SEEK_END);
+
+ info.handle = gem;
+ if (drmCommandWriteRead(bufmgr_sprd->fd,
+ DRM_SPRD_GEM_GET,
+ &info,
+ sizeof(struct drm_sprd_gem_info)))
+ {
+ TBM_SPRD_LOG ("error bo:%p Cannot get gem info from gem:%d, fd:%d (%s)\n",
+ bo, gem, key, strerror(errno));
+ return 0;
+ }
+
+ if (real_size == -1)
+ real_size = info.size;
+
+ bo_sprd = calloc (1, sizeof(struct _tbm_bo_sprd));
+ if (!bo_sprd)
+ {
+ TBM_SPRD_LOG ("error bo:%p fail to allocate the bo private\n", bo);
+ return 0;
+ }
+
+ bo_sprd->fd = bufmgr_sprd->fd;
+ bo_sprd->gem = gem;
+ bo_sprd->size = real_size;
+ bo_sprd->flags_sprd = info.flags;
+ bo_sprd->flags_tbm = _get_tbm_flag_from_sprd (bo_sprd->flags_sprd);
+
+ bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
+ if (!bo_sprd->name)
+ {
+ TBM_SPRD_LOG ("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
+ bo, gem, key, strerror(errno));
+ free (bo_sprd);
+ return 0;
+ }
+
+ /* add bo to hash */
+ PrivGem *privGem = NULL;
+ int ret;
+
+ ret = drmHashLookup (bufmgr_sprd->hashBos, bo_sprd->name, (void**)&privGem);
+ if (ret == 0)
+ {
+ privGem->ref_count++;
+ }
+ else if (ret == 1)
+ {
+ privGem = calloc (1, sizeof(PrivGem));
+ if (!privGem)
+ {
+ TBM_SPRD_LOG ("[libtbm-sprd:%d] "
+ "error %s:%d Fail to calloc privGem\n",
+ getpid(), __FUNCTION__, __LINE__);
+ free (bo_sprd);
+ return 0;
+ }
+
+ privGem->ref_count = 1;
+ if (drmHashInsert (bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0)
+ {
+ TBM_SPRD_LOG ("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
+ bo, bo_sprd->name, gem, key);
+ }
+ }
+ else
+ {
+ TBM_SPRD_LOG ("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
+ bo, bo_sprd->name, gem, key);
+ }
+
+ DBG (" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
+ bo,
+ bo_sprd->gem, bo_sprd->name,
+ bo_sprd->dmabuf,
+ key,
+ bo_sprd->flags_tbm, bo_sprd->flags_sprd,
+ bo_sprd->size);
+
+ return (void *)bo_sprd;
+}
+