libdrm移植到arm设备

news/2025/2/6 12:55:08 标签: arm开发

一、环境资源要求

下载libdrm

Index of /libdrm

这边使用的是2.4.114版本,版本太高对meson版本要求也很高,为了省事用apt安装meson就不用太高版本了,1.x版本虽然使用makefile编译方便但是太老,对应用支持不太好。

https://dri.freedesktop.org/libdrm/libdrm-2.4.114.tar.xz

由于libdrm项目是基于meson构建的,所以需要安装meson

sudo apt install meson

二、代码编译

1、解压并cd到代码目录下 

cd libdrm-2.4.114

2、创建目录

#建立安装目录
mkdir install
#创建编译目录
mkdir build

3、创建cross_file.txt文件

#创建并编写cross_file.txt文件,用于配置交叉编译环境
vi cross_file.txt

在cross_file.txt添加如下配置项

[binaries]
c = 'arm-linux-gnueabihf-gcc'
cpp = 'arm-linux-gnueabihf-g++'
ar = 'arm-linux-gnueabihf-ar'
strip = 'arm-linux-gnueabihf-strip'

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

4、配置编译选项

# cd到build目录
cd build
# 配置编译选项,根据自己平台将对应平台的false替换为true
meson --prefix=$(pwd)/../install \
	  --cross-file=../cross_file.txt \
	  -D amdgpu=false \       #amd集显平台
	  -D etnaviv=false \      #vivante图芯gpu支持
	  -D exynos=false \       #三星平台
	  -D freedreno=false \    #高通平台
	  -D freedreno-kgsl=false \ #高通平台
	  -D intel=false \        #intel集显平台
	  -D nouveau=false \      #nvdia平台
	  -D omap=false \         #ti平台
	  -D radeon=false \       #amd独显平台
	  -D tegra=false \        #nvdia tegra(switch)平台
	  -D vc4=false \          #博通VC4平台
	  -D libkms=false \       #drm kms库
	  -D man-pages=false \    #man手册
	  -D udev=false \         #udev支持
	  -D valgrind=false \     #内存测试
	  -D cairo-tests=false \  #cairo语言测试
	  -D vmwgfx=false         #VMWare图形驱动支持
      -D install-test-programs=true \    #安装测试程序,建议安装,便于检测排查问题。

5、编译安装

#编译并安装
ninja && ninja install
#完成后在../install目录可以能得到对应的文件

三、环境测试

1、modetest测试

#modetest 参数
modetest -h  #帮助
 Query options:#用于查询的参数选项

        -c      list connectors #列举出所有的connectors
        -e      list encoders   #列举出所有的encoders   
        -f      list framebuffers #列举出所有的framebuffers 
        -p      list CRTCs and planes (pipes) #列举出所有的CRTCs和planes 

 Test options:#用于测试的参数选项
		#-P给CRTC指定plane
        -P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]  set a plane 
        #-s 设置输出模式,选择connector和crtc
        -s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>] set a mode 
        -C      test hw cursor
        -v      test vsynced page flipping
        -r      set the preferred mode for all connectors
        -w <obj_id>:<prop_name>:<value> set property
        -a      use atomic API
        -F pattern1,pattern2    specify fill patterns

 Generic options:#指定打开设备、驱动

        -d      drop master after mode set
        -M module       use the given driver
        -D device       use the given device

        Default is to dump all info.

#例子
#-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]
#-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]  set a plane 
modetest  -s 37@35:1024x768  -P 33@35:1024x768  #运行成功会有屏幕彩块显示
#37是连接器号,通过modetest -c查询
#两个35都是crtc的号,通过modetest -p可以查询到带分辨率的接口crtc号,以及显示分辨率。

2、代码测试

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#define WIDTH 800     //修改为屏幕对应分辨率宽度
#define HEIGHT 600    //修改为屏幕对应分辨率高度

int main(int argc, char **argv) {
    int fd;
    drmModeRes *resources;
    drmModeConnector *connector;
    drmModeEncoder *encoder;
    drmModeCrtc *crtc;
    uint32_t *framebuffer;
    uint32_t handle;
    uint32_t stride;
    uint32_t size;
    int ret;

    // 打开DRM设备
    fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
    if (fd < 0) {
        perror("Failed to open DRM device");
        return 1;
    }

    // 获取资源
    resources = drmModeGetResources(fd);
    if (!resources) {
        perror("Failed to get DRM resources");
        close(fd);
        return 1;
    }

    // 查找连接
    for (int i = 0; i < resources->count_connectors; i++) {
        connector = drmModeGetConnector(fd, resources->connectors[i]);
        if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) {
            break;
        }
        drmModeFreeConnector(connector);
    }

    if (!connector) {
        fprintf(stderr, "No connected connector found\n");
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 查找编码器
    encoder = drmModeGetEncoder(fd, connector->encoder_id);
    if (!encoder) {
        perror("Failed to get encoder");
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 获取CRTC
    crtc = drmModeGetCrtc(fd, encoder->crtc_id);
    if (!crtc) {
        perror("Failed to get CRTC");
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 计算帧缓冲区大小
    stride = WIDTH * 4; // 假设每个像素4字节(32位颜色)
    size = stride * HEIGHT;

    // 创建帧缓冲区
    ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMMY, &handle);
    if (ret < 0) {
        perror("Failed to create dummy buffer");
        drmModeFreeCrtc(crtc);
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 映射帧缓冲区到内存
    framebuffer = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, handle);
    if (framebuffer == MAP_FAILED) {
        perror("Failed to map framebuffer");
        drmModeFreeCrtc(crtc);
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 填充帧缓冲区
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            uint32_t color = (x * 255 / WIDTH) << 16 | (y * 255 / HEIGHT) << 8 | 255;
            framebuffer[y * WIDTH + x] = color;
        }
    }

    // 设置CRTC
    ret = drmModeSetCrtc(fd, crtc->crtc_id, handle, 0, 0, &connector->connector_id, 1, &connector->modes[0]);
    if (ret < 0) {
        perror("Failed to set CRTC");
        munmap(framebuffer, size);
        drmModeFreeCrtc(crtc);
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    // 等待用户输入
    printf("Press Enter to exit...\n");
    getchar();

    // 恢复原来的CRTC
    drmModeSetCrtc(fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &connector->connector_id, 1, &crtc->mode);

    // 清理资源
    munmap(framebuffer, size);
    drmModeFreeCrtc(crtc);
    drmModeFreeEncoder(encoder);
    drmModeFreeConnector(connector);
    drmModeFreeResources(resources);
    close(fd);

    return 0;
}

编译代码

gcc -o drm_draw main.c -ldrm

# 交叉编译 gcc可替换arm-linux-gnueabihf-gcc, -ldrm前加上drm库路径 -L /path/libdrm/lib/ 以及加上include路径 -I /path/libdrm/include/

 运行代码

sudo ./drm_draw

四、参考文章

DRM框架与libdrm移植-CSDN博客


http://www.niftyadmin.cn/n/5843004.html

相关文章

【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信

引言 我们之前了解了在不同场景下,Kubernetes中Pod之间的通信是如何路由的。 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信现在,我们来看看在集群中,Pod与服务之间的通信是如何…

使用PaddlePaddle实现逻辑回归:从训练到模型保存与加载

1. 引入必要的库 首先&#xff0c;需要引入必要的库。PaddlePaddle用于构建和训练模型&#xff0c;pandas和numpy用于数据处理&#xff0c;matplotlib用于结果的可视化。 import paddle import pandas as pd import numpy as np import matplotlib.pyplot as plt 2. 加载自定…

腾讯云 TI 平台部署与调用DeepSeek-R1大模型的实战指南

今天我们将继续探讨如何部署一个私有化的 DeepSeek-R1 大模型&#xff0c;具体的部署过程我们将利用腾讯云的 TI 平台进行操作。当前&#xff0c;腾讯云 TI 平台为用户提供了免费体验的满血版 DeepSeek-R1 大模型&#xff0c;同时该平台还提供了开放的 API 接口服务&#xff0c…

【Rust自学】20.2. 最后的项目:多线程Web服务器

说句题外话&#xff0c;这篇文章非常要求Rust的各方面知识&#xff0c;最好看一下我的【Rust自学】专栏的所有内容。这篇文章也是整个专栏最长&#xff08;4762字&#xff09;的文章&#xff0c;需要多次阅读消化&#xff0c;最好点个收藏&#xff0c;免得刷不到了。 喜欢的话…

缓存类为啥使用 unordered_map 而不是 map

性能考虑&#xff1a; std::unordered_map 是基于哈希表实现的&#xff0c;而 std::map 是基于红黑树实现的。对于查找操作&#xff0c;std::unordered_map 的平均查找时间复杂度是 O ( 1 ) O(1) O(1)&#xff0c;而 std::map 的查找时间复杂度是 O ( l o g n ) O(log n) O(l…

JavaScript系列(60)--云原生应用开发详解

JavaScript云原生应用开发详解 ☁️ 今天&#xff0c;让我们深入探讨JavaScript的云原生应用开发。云原生是一种构建和运行应用程序的方法&#xff0c;充分利用云计算模型的优势&#xff0c;使应用具有更好的可扩展性、弹性和敏捷性。 云原生基础架构 &#x1f31f; &#x1…

【系统架构设计师】操作系统 ② ( 存储管理 | 页式存储 | 逻辑地址 与 物理地址 | 页表结构 | 物理内存淘汰机制 )

文章目录 一、页式存储1、CPU 调用数据2、内存存储数据弊端3、分页存储4、逻辑地址 和 物理地址 的结构5、逻辑地址 和 物理地址 的结构 示例6、页式存储 优缺点 二、逻辑地址 与 物理地址1、逻辑地址2、物理地址3、逻辑地址 与 物理地址 区别4、逻辑地址 与 物理地址 的转换 三…

Java 大视界 -- Java 大数据在智慧文旅中的应用与体验优化(74)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…