DRM DUMB相关说明

概述

笔者在涉及RK平台中如下链路时,对drm申请的buffer相关字段有些疑惑。因此写此贴作为一个记录。

mppdec解码 --> rga缩放 --> drm显示

流程解析

如下接口是申请drm类型的dumb。首先需要传入的fd是设备的文件句柄,比如/dev/dri/card0。随后通过drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg)申请到一个DUMB的内存块,此时出现了handle,随后又通过drmPrimeHandleToFD获取到一个fd(对应buff_fd)。

static struct bo_new *
bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp)
{
    struct drm_mode_create_dumb arg;
    struct bo_new *bo;
    int ret;

    bo = calloc(1, sizeof(*bo));
    if (bo == NULL) {
        fprintf(stderr, "failed to allocate buffer object\n");
        return NULL;
    }

    memset(&arg, 0, sizeof(arg));
    arg.bpp = bpp;
    arg.width = width;
    arg.height = height;

    ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
    if (ret) {
        fprintf(stderr, "failed to create dumb buffer: %s\n",
            strerror(errno));
        free(bo);
        return NULL;
    }

    bo->fd = fd;
    bo->handle = arg.handle;
    bo->size = arg.size;
    bo->pitch = arg.pitch;

    drmPrimeHandleToFD(fd, arg.handle, 0, &bo->buff_fd);

    return bo;
}

上述函数执行完毕,我们获取到drm buff的一个handle和一个fd。但是在该drm buff送往drm显示时,还需要再进行一次转换(通过接口drmModeAddFB2 ),需要获取一个fb(对应代码fb_id)。

  kmsmem = calloc(sizeof(KMSMEM), 1);
  kmsmem->bo = bo_create(self->fd, vinfo->format,
                   vinfo->width, vinfo->height,
                   handles, pitches,
                   offsets, UTIL_PATTERN_TILES);

  printf("bo handles: %d, %d, %d, %d, ptr %p\n", handles[0],
      handles[1], handles[2], handles[3], kmsmem->bo->ptr);

  ret = drmModeAddFB2 (self->fd, vinfo->width, vinfo->height,
                        vinfo->format, handles, pitches,
                        offsets, &kmsmem->fb_id, 0);

在drm送显时,则是传入上文提到的fb,比如如下代码中的fb_id

  ret = drmModeSetPlane (self->fd, self->plane_id, self->crtc_id, fb_id, 0,
      result.x, result.y, result.w, result.h,
      /* source/cropping coordinates are given in Q16 */
      src.x << 16, src.y << 16, src.w << 16, src.h << 16);

总结

上文中涉及drm buff的三个变量:handle,fd,fb;我的理解如下:

  • handle:驱动层的标识符,因此通过drmIoctl像驱动获取到的标识符便为handle形式。
  • fd:用户层的标识符,用户可通过该fd,对buffer进行map处理。在rga处理时,可直接使用drm buff的fd作为接口入参。
    // rk扩展ffmpeg解码器时自定义的结构。代码中的fd就是drmbuff的fd。
    drm_fram_desc = (AVDRMFrameDescriptor*)frame->data[0];
    memset(&src_info, 0, sizeof(rga_info_t));
    src_info.fd = drm_fram_desc->objects[0].fd;
    src_info.mmuFlag = 1;

    // 目标为新申请的drm buff的fd,rga缩放后,新的图像存放此处。
    memset(&dst_info, 0, sizeof(rga_info_t));
    dst_info.fd = buffer->bo->buff_fd;
    dst_info.mmuFlag = 1;

    /********** set the rect_info **********/
    rga_set_rect(&src_info.rect, 0, 0, srcWidth, srcHeight, srcWidth/*stride*/, srcHeight, srcFormat);
    rga_set_rect(&dst_info.rect, 0, 0, dstWidth, dstHeight, dstWidth/*stride*/, dstHeight, dstFormat);
    src_info.rotation = rotate;

    ret = c_RkRgaBlit(&src_info, &dst_info, NULL);
    if (ret) {
        av_log(NULL, AV_LOG_FATAL, "rk rga split func failed!\n");
        return;
    }
  • fb:我理解为framebuff的标识符,用于额外封装drm buff为framebuff结构,然后才能通过drm接口送显。之所以封装,是因为framebuff额外提供了当前buff的宽高等信息。
  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值