187 lines
5.3 KiB
C
187 lines
5.3 KiB
C
// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "drm_func.h"
|
|
#include <dlfcn.h>
|
|
|
|
int drm_init(drm_context *drm_ctx)
|
|
{
|
|
static const char *card = "/dev/dri/card0";
|
|
int flag = O_RDWR;
|
|
int drm_fd = -1;
|
|
|
|
drm_fd = open(card, flag);
|
|
if (drm_fd < 0)
|
|
{
|
|
printf("failed to open %s\n", card);
|
|
return -1;
|
|
}
|
|
|
|
drm_ctx->drm_handle = dlopen("libdrm.so", RTLD_LAZY);
|
|
|
|
if (!drm_ctx->drm_handle)
|
|
{
|
|
printf("failed to dlopen libdrm.so\n");
|
|
printf("dlopen error: %s\n", dlerror());
|
|
drm_deinit(drm_ctx, drm_fd);
|
|
return -1;
|
|
}
|
|
|
|
drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl");
|
|
if (drm_ctx->io_func == NULL)
|
|
{
|
|
dlclose(drm_ctx->drm_handle);
|
|
drm_ctx->drm_handle = NULL;
|
|
drm_deinit(drm_ctx, drm_fd);
|
|
printf("failed to dlsym drmIoctl\n");
|
|
return -1;
|
|
}
|
|
return drm_fd;
|
|
}
|
|
|
|
void drm_deinit(drm_context *drm_ctx, int drm_fd)
|
|
{
|
|
if (drm_ctx->drm_handle)
|
|
{
|
|
dlclose(drm_ctx->drm_handle);
|
|
drm_ctx->drm_handle = NULL;
|
|
}
|
|
if (drm_fd > 0)
|
|
{
|
|
close(drm_fd);
|
|
}
|
|
}
|
|
|
|
void *drm_buf_alloc(drm_context *drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int *fd, unsigned int *handle, size_t *actual_size)
|
|
{
|
|
// printf("0: Width %d, Heigh %d, bpp %d\n", TexWidth, TexHeight, bpp);
|
|
// printf("fd: %d, handle: %d, size: %d\n", fd, handle, actual_size);
|
|
int ret;
|
|
if (drm_ctx == NULL)
|
|
{
|
|
printf("drm context is unvalid\n");
|
|
return NULL;
|
|
}
|
|
char *map = NULL;
|
|
|
|
// printf("Width %d, Heigh %d\n", TexWidth, TexHeight);
|
|
|
|
void *vir_addr = NULL;
|
|
struct drm_prime_handle fd_args;
|
|
struct drm_mode_map_dumb mmap_arg;
|
|
struct drm_mode_destroy_dumb destory_arg;
|
|
|
|
struct drm_mode_create_dumb alloc_arg;
|
|
|
|
memset(&alloc_arg, 0, sizeof(alloc_arg));
|
|
alloc_arg.bpp = bpp;
|
|
alloc_arg.width = TexWidth;
|
|
alloc_arg.height = TexHeight;
|
|
// alloc_arg.flags = ROCKCHIP_BO_CONTIG;
|
|
|
|
// printf("2: Width %d, Heigh %d\n", TexWidth, TexHeight);
|
|
|
|
//获取handle和size
|
|
ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
|
|
// printf("3: Width %d, Heigh %d\n", TexWidth, TexHeight);
|
|
if (ret)
|
|
{
|
|
printf("failed to create dumb buffer: %s\n", strerror(errno));
|
|
return NULL;
|
|
}
|
|
// printf("4: Width %d, Heigh %d\n", TexWidth, TexHeight);
|
|
if (handle != NULL)
|
|
{
|
|
*handle = alloc_arg.handle;
|
|
}
|
|
// printf("5: Width %d, Heigh %d\n", TexWidth, TexHeight);
|
|
if (actual_size != NULL)
|
|
{
|
|
*actual_size = alloc_arg.size;
|
|
}
|
|
// printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size);
|
|
// printf("out handle= %d\n",alloc_arg.handle);
|
|
|
|
//获取fd
|
|
memset(&fd_args, 0, sizeof(fd_args));
|
|
fd_args.fd = -1;
|
|
fd_args.handle = alloc_arg.handle;
|
|
;
|
|
fd_args.flags = 0;
|
|
ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args);
|
|
if (ret)
|
|
{
|
|
printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle);
|
|
return NULL;
|
|
}
|
|
// printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd);
|
|
if (fd != NULL)
|
|
{
|
|
*fd = fd_args.fd;
|
|
}
|
|
|
|
//获取虚拟地址
|
|
memset(&mmap_arg, 0, sizeof(mmap_arg));
|
|
mmap_arg.handle = alloc_arg.handle;
|
|
|
|
ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
|
|
if (ret)
|
|
{
|
|
printf("failed to create map dumb: %s\n", strerror(errno));
|
|
vir_addr = NULL;
|
|
goto destory_dumb;
|
|
}
|
|
vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset);
|
|
if (map == MAP_FAILED)
|
|
{
|
|
printf("failed to mmap buffer: %s\n", strerror(errno));
|
|
vir_addr = NULL;
|
|
goto destory_dumb;
|
|
}
|
|
// printf("alloc map=%x \n",map);
|
|
return vir_addr;
|
|
destory_dumb:
|
|
memset(&destory_arg, 0, sizeof(destory_arg));
|
|
destory_arg.handle = alloc_arg.handle;
|
|
ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
|
|
if (ret)
|
|
printf("failed to destory dumb %d\n", ret);
|
|
return vir_addr;
|
|
}
|
|
|
|
int drm_buf_destroy(drm_context *drm_ctx, int drm_fd, int buf_fd, int handle, void *drm_buf, size_t size)
|
|
{
|
|
int ret = -1;
|
|
if (drm_buf == NULL)
|
|
{
|
|
printf("drm buffer is NULL\n");
|
|
return -1;
|
|
}
|
|
|
|
munmap(drm_buf, size);
|
|
|
|
struct drm_mode_destroy_dumb destory_arg;
|
|
memset(&destory_arg, 0, sizeof(destory_arg));
|
|
destory_arg.handle = handle;
|
|
ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
|
|
if (ret)
|
|
printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno));
|
|
if (buf_fd > 0)
|
|
{
|
|
close(buf_fd);
|
|
}
|
|
|
|
return ret;
|
|
}
|