mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-06 01:26:49 +08:00
[drm]: use mmap() in native way for GNU Linux target
The "[drm]: fix runtime error for 32bit library" is hack way, it won't work at GNU Linux platform. Also you need to check _FILE_OFFSET_BITS and _LARGEFILE64_SOURCE before use the mmap64(). For the normal mmap() with glibc, we only request to check offset is aligned with page size but not the lenght. But that doesn't apply for the memory from the drm device, also the android use a different rule. I decide not to map all the buffer to cpu at beginning since most of them won't be access by the cpu. Change-Id: I74ac7b5b63d45029cae076985a3d0b4526c62bbc Signed-off-by: Randy Li <randy.li@rock-chips.com>
This commit is contained in:
@@ -44,6 +44,37 @@ static RK_U32 drm_debug = 0;
|
||||
|
||||
#define drm_dbg(flag, fmt, ...) _mpp_dbg_f(drm_debug, flag, fmt, ## __VA_ARGS__)
|
||||
|
||||
#if defined(ANDROID) && !defined(__LP64__)
|
||||
#include <errno.h> /* for EINVAL */
|
||||
|
||||
extern void *__mmap2(void *, size_t, int, int, int, size_t);
|
||||
|
||||
static inline void *drm_mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, loff_t offset)
|
||||
{
|
||||
/* offset must be aligned to 4096 (not necessarily the page size) */
|
||||
if (offset & 4095) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
|
||||
}
|
||||
|
||||
# define drm_munmap(addr, length) \
|
||||
munmap(addr, length)
|
||||
|
||||
#else
|
||||
|
||||
/* assume large file support exists */
|
||||
# define drm_mmap(addr, length, prot, flags, fd, offset) \
|
||||
mmap(addr, length, prot, flags, fd, offset)
|
||||
|
||||
# define drm_munmap(addr, length) \
|
||||
munmap(addr, length)
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
RK_U32 alignment;
|
||||
RK_S32 drm_device;
|
||||
@@ -65,28 +96,6 @@ static int drm_ioctl(int fd, int req, void *arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* drm_mmap(int fd, size_t len, int prot, int flags, loff_t offset)
|
||||
{
|
||||
static unsigned long pagesize_mask = 0;
|
||||
func_mmap64 fp_mmap64 = mpp_rt_get_mmap64();
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (!pagesize_mask)
|
||||
pagesize_mask = sysconf(_SC_PAGESIZE) - 1;
|
||||
|
||||
len = (len + pagesize_mask) & ~pagesize_mask;
|
||||
|
||||
if (offset & 4095)
|
||||
return NULL;
|
||||
|
||||
if (fp_mmap64)
|
||||
return fp_mmap64(NULL, len, prot, flags, fd, offset);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags)
|
||||
{
|
||||
int ret;
|
||||
@@ -100,9 +109,8 @@ static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags)
|
||||
return -EINVAL;
|
||||
|
||||
ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*map_fd = dph.fd;
|
||||
|
||||
@@ -130,48 +138,12 @@ static int drm_fd_to_handle(int fd, int map_fd, RK_U32 *handle, RK_U32 flags)
|
||||
}
|
||||
|
||||
*handle = dph.handle;
|
||||
|
||||
drm_dbg(DRM_FUNCTION, "get handle %d", *handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int drm_map(int fd, RK_U32 handle, size_t length, int prot,
|
||||
int flags, unsigned char **ptr, int *map_fd)
|
||||
{
|
||||
int ret;
|
||||
struct drm_mode_map_dumb dmmd;
|
||||
memset(&dmmd, 0, sizeof(dmmd));
|
||||
dmmd.handle = handle;
|
||||
|
||||
if (map_fd == NULL)
|
||||
return -EINVAL;
|
||||
if (ptr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
ret = drm_handle_to_fd(fd, handle, map_fd, 0);
|
||||
drm_dbg(DRM_FUNCTION, "drm_map fd %d", *map_fd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
|
||||
if (ret < 0) {
|
||||
close(*map_fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_dbg(DRM_FUNCTION, "dev fd %d length %d", fd, length);
|
||||
|
||||
*ptr = drm_mmap(fd, length, prot, flags, dmmd.offset);
|
||||
if (*ptr == MAP_FAILED) {
|
||||
close(*map_fd);
|
||||
*map_fd = -1;
|
||||
mpp_err("mmap failed: %s\n", strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int drm_alloc(int fd, size_t len, size_t align, RK_U32 *handle)
|
||||
{
|
||||
int ret;
|
||||
@@ -269,13 +241,14 @@ static MPP_RET os_allocator_drm_alloc(void *ctx, MppBufferInfo *info)
|
||||
return ret;
|
||||
}
|
||||
drm_dbg(DRM_FUNCTION, "handle %d", (RK_U32)((intptr_t)info->hnd));
|
||||
ret = drm_map(p->drm_device, (RK_U32)((intptr_t)info->hnd), info->size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
(unsigned char **)&info->ptr, &info->fd);
|
||||
ret = drm_handle_to_fd(p->drm_device, (RK_U32)((intptr_t)info->hnd),
|
||||
&info->fd, 0);
|
||||
|
||||
if (ret) {
|
||||
mpp_err("os_allocator_drm_alloc drm_map failed ret %d\n", ret);
|
||||
mpp_err("os_allocator_drm_alloc handle_to_fd failed ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
info->ptr = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -287,29 +260,15 @@ static MPP_RET os_allocator_drm_import(void *ctx, MppBufferInfo *data)
|
||||
memset(&dmmd, 0, sizeof(dmmd));
|
||||
|
||||
drm_dbg(DRM_FUNCTION, "enter");
|
||||
// NOTE: do not use the original buffer fd,
|
||||
// use dup fd to avoid unexpected external fd close
|
||||
data->fd = dup(data->fd);
|
||||
|
||||
ret = drm_fd_to_handle(p->drm_device, data->fd, (RK_U32 *)&data->hnd, 0);
|
||||
|
||||
drm_dbg(DRM_FUNCTION, "get handle %d", (intptr_t)(data->hnd));
|
||||
|
||||
dmmd.handle = (intptr_t)data->hnd;
|
||||
|
||||
ret = drm_ioctl(p->drm_device, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
drm_dbg(DRM_FUNCTION, "dev fd %d length %d", p->drm_device, data->size);
|
||||
|
||||
data->ptr = drm_mmap(p->drm_device, data->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dmmd.offset);
|
||||
if (data->ptr == MAP_FAILED) {
|
||||
mpp_err("mmap failed: %s\n", strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
ret = drm_handle_to_fd(p->drm_device, (RK_U32)((intptr_t)data->hnd),
|
||||
&data->fd, 0);
|
||||
|
||||
data->ptr = NULL;
|
||||
drm_dbg(DRM_FUNCTION, "leave");
|
||||
|
||||
return ret;
|
||||
@@ -326,11 +285,11 @@ static MPP_RET os_allocator_drm_free(void *ctx, MppBufferInfo *data)
|
||||
p = (allocator_ctx_drm *)ctx;
|
||||
|
||||
if (data->ptr) {
|
||||
munmap(data->ptr, data->size);
|
||||
drm_munmap(data->ptr, data->size);
|
||||
data->ptr = NULL;
|
||||
}
|
||||
|
||||
close(data->fd);
|
||||
|
||||
return drm_free(p->drm_device, (RK_U32)((intptr_t)data->hnd));
|
||||
}
|
||||
|
||||
@@ -346,13 +305,52 @@ static MPP_RET os_allocator_drm_close(void *ctx)
|
||||
|
||||
p = (allocator_ctx_drm *)ctx;
|
||||
drm_dbg(DRM_FUNCTION, "close fd %d", p->drm_device);
|
||||
|
||||
ret = close(p->drm_device);
|
||||
mpp_free(p);
|
||||
if (ret < 0)
|
||||
return (MPP_RET) - errno;
|
||||
|
||||
return MPP_OK;
|
||||
}
|
||||
|
||||
static MPP_RET os_allocator_drm_mmap(void *ctx, MppBufferInfo *data)
|
||||
{
|
||||
allocator_ctx_drm *p;
|
||||
MPP_RET ret = MPP_OK;
|
||||
if (NULL == ctx) {
|
||||
mpp_err("os_allocator_close do not accept NULL input\n");
|
||||
return MPP_ERR_NULL_PTR;
|
||||
}
|
||||
p = (allocator_ctx_drm *)ctx;
|
||||
|
||||
if (NULL == ctx)
|
||||
return MPP_ERR_NULL_PTR;
|
||||
|
||||
if (NULL == data->ptr) {
|
||||
struct drm_mode_map_dumb dmmd;
|
||||
|
||||
memset(&dmmd, 0, sizeof(dmmd));
|
||||
dmmd.handle = (RK_U32)(intptr_t)data->hnd;
|
||||
|
||||
ret = drm_ioctl(p->drm_device, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
|
||||
if (ret) {
|
||||
mpp_err("map_dumb failed: %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->ptr = drm_mmap(NULL, data->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, p->drm_device, dmmd.offset);
|
||||
if (data->ptr == MAP_FAILED) {
|
||||
mpp_err("mmap failed: %s\n", strerror(errno));
|
||||
data->ptr = NULL;
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
os_allocator allocator_drm = {
|
||||
.open = os_allocator_drm_open,
|
||||
.close = os_allocator_drm_close,
|
||||
@@ -360,5 +358,5 @@ os_allocator allocator_drm = {
|
||||
.free = os_allocator_drm_free,
|
||||
.import = os_allocator_drm_import,
|
||||
.release = os_allocator_drm_free,
|
||||
.mmap = NULL,
|
||||
.mmap = os_allocator_drm_mmap,
|
||||
};
|
||||
|
@@ -19,13 +19,6 @@
|
||||
|
||||
#include "mpp_common.h"
|
||||
|
||||
/*
|
||||
* Runtime function detection is for rockchip software platform detection
|
||||
*/
|
||||
|
||||
typedef void *(*func_mmap64)(void* addr, size_t length, int prot, int flags,
|
||||
int fd, off_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -35,8 +28,6 @@ extern "C" {
|
||||
* runtime environment. This is usefull on product environemnt.
|
||||
*/
|
||||
|
||||
func_mmap64 mpp_rt_get_mmap64();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -19,25 +19,3 @@
|
||||
#endif
|
||||
|
||||
#include "mpp_runtime.h"
|
||||
|
||||
static func_mmap64 mpp_rt_mmap64 = NULL;
|
||||
|
||||
func_mmap64 mpp_rt_get_mmap64()
|
||||
{
|
||||
#ifdef RKPLATFORM
|
||||
static RK_U32 once = 1;
|
||||
|
||||
if (once) {
|
||||
void *libc_hdl = dlopen("libc", RTLD_LAZY);
|
||||
if (libc_hdl) {
|
||||
mpp_rt_mmap64 = (func_mmap64)dlsym(libc_hdl, "mmap64");
|
||||
dlclose(libc_hdl);
|
||||
}
|
||||
|
||||
once = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mpp_rt_mmap64;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user