ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

树莓派驱动DLP微投:framebuffer直写854×480显示实战

树莓派驱动DLP微投:framebuffer直写854×480显示实战 最近有个活儿要用树莓派驱动一块DLP微投影模组型号是TI的DLPDLCR230NPEVM要求在Linux下通过framebuffer直接显示图片。这套东西不是插上就能用的里面有很多细节HDMI时序要手动配、framebuffer的像素格式要对齐、DMD的驱动方式也不是普通显示器那么简单。搞了几天踩了不少坑把完整过程写下来给后面做类似项目的朋友一个参考。先说结论树莓派通过HDMI连接DLPDLCR230NPEVM在config.txt里手动指定854x48060Hz的自定义时序系统启动后就能在/dev/fb0上操作用工具或者写几行代码把图片数据写进去DLP板就会把画面投影出来。整个过程不需要编译内核模块不需要复杂的驱动程序Linux自带的framebuffer机制就够用重点在于把显示参数和像素格式搞清楚。这套方案适合谁如果你在做微型投影、DLP光固化3D打印、结构光三维扫描、嵌入式广告机或者单纯想把DMD当实验用的空间光调制器都可以参考这条链路。下面从硬件连接、系统配置、framebuffer原理到实际写代码显示图片全部分享出来。1. 项目全景当树莓派遇到DLP微投1.1 DLPDLCR230NPEVM到底是什么DLPDLCR230NPEVM是德州仪器出的DLP评估模块核心是一颗DLP230NP数字微镜器件0.23英寸对角线854x480分辨率。DMD表面密密麻麻排布着几百万个微镜每个微镜只有5.4微米左右通过静电驱动在±12度两个位置之间高速翻转。微镜翻到“开”位置时把照明光反射进投影镜头形成亮像素翻到“关”位置就把光反射到吸收器上形成暗像素。配合RGB三色LED时序点亮就能投出彩色画面。这块评估板把DMD、DLPC3436控制器、LED驱动、HDMI接口、光学引擎全部整合在一小块板子上。DLPC3436是显示控制核心内部带一个ARM Cortex-M3处理器负责解析输入图像信号、控制DMD微镜翻转时序、管理LED电流和颜色切换。板子上有mini-HDMI输入口可以直接接树莓派的HDMI输出也有一个40pin的并行RGB扩展接口可以接FPGA或者MCU。我第一次拿到这板子时以为跟普通显示器一样HDMI插上就能出画面结果树莓派开机后DLP板上完全没有信号。原因在于这块EVM板不像普通显示器那样提供完整的EDID信息树莓派的HDMI输出无法自动协商到正确分辨率默认跑到了640x480甚至更低DLP板的视频前端不认识这个时序自然不出图。1.2 为什么选framebuffer而不是普通桌面显示有些人可能会问直接用树莓派桌面系统、HDMI接DLP板不就完事了吗理论上可以但有几个实际问题。第一树莓派桌面版默认启动X11/Wayland桌面环境会抢占显示输出画面内容不可控。投影应用要的是直接把某张图片或者某段动画写满整个DMD屏幕而不是在桌面上开个窗口。第二桌面环境带来的延迟和调度不可控。在光固化3D打印或者结构光投影场景里每一帧图像的曝光时间需要精确控制桌面合成器会在中间插入鼠标指针、窗口装饰、屏幕保护等元素这在工业应用里是致命的。第三framebuffer接口极度简洁。它把显示设备抽象成一个字符设备和一块内存映射区域write、mmap、ioctl三个操作就能完成全部显示控制。这非常适合嵌入式Linux场景不依赖任何桌面服务开机进命令行模式下就能直接操作。1.3 这套链路能做什么树莓派加DLPDLCR230NPEVM的组合能做很多有意思的事情。最简单的就是当投影仪用树莓派播放视频或者显示图片DLP板投出854x480的画面亮度虽然不如商用投影仪但胜在体积小、功耗低、可嵌入到自制设备里。更应用性的是光固化3D打印。把树莓派输出的黑白切片图像送到DMD上配合405nm紫外LED和Z轴步进电机就能搭出一台桌面级DLP光固化打印机。帧率不用高但每张图的曝光时间必须稳定framebuffer直写完全可以满足。还有结构光三维扫描DMD用来投影格雷码或者相移条纹相机同步拍摄通过图像处理恢复物体三维形貌。这套方案相比LCD投影的优势是刷新率高、对比度高、像素边缘锐利结构光条纹质量好。搞光学实验的人也可以用这块板子做空间光调制器把特定的相位图或者光斑图案投到光路上只要输入是黑白图像就非常适合。2. 硬件连接与显示链路搭建2.1 硬件清单与接线要点整个过程需要的硬件很常规树莓派一块我用的是树莓派4B树莓派3B/5也都可以性能影响不大DLPDLCR230NPEVM评估板一块建议确认出厂固件已经烧好mini-HDMI转标准HDMI线或者转接头。DLPDLCR230NPEVM上用的是mini-HDMI座树莓派是标准HDMI输出所以需要一根mini-HDMI公转HDMI公的线或者HDMI公转mini-HDMI公的转接线5V电源给树莓派另配一个5V电源给DLP板。特别注意DLP板不能指望从HDMI口取电必须单独供电一张TF卡烧录Raspberry Pi OS Lite不需要桌面版命令行版本就够了一张要显示的测试图片建议直接用854x480分辨率接线顺序有讲究。先把DLP板的电源接好确认板上的LED指示灯亮起来再把mini-HDMI线插到DLP板HDMI端插到树莓派。供电顺序建议DLP板先上电然后再启动树莓派。我踩过一个坑树莓派先启动再给DLP板上电时HDMI协商偶发失败表现为系统启动LOG里没有显示输出fbset查到的分辨率也不对。2.2 树莓派显示输出配置核心时序参数详解树莓派默认的显示输出是自动协商的通过读取显示器EDID来决定分辨率。DLPDLCR230NPEVM的HDMI接口不主动上报完整EDID所以必须强制树莓派输出指定的自定义时序。修改/boot/config.txt追加以下内容hdmi_force_hotplug1 hdmi_group2 hdmi_mode87 hdmi_timings854 0 20 20 28 480 0 2 2 4 0 0 27000000 4 0 hdmi_drive2逐项解释这段配置的作用。hdmi_force_hotplug1是强制树莓派认为HDMI线已经插入不走EDID检测流程。没有这一项树莓派可能压根不启动HDMI输出通道。hdmi_group2表示采用CEA时序标准这是HDMI设备常用的标准组。hdmi_mode87表示使用自定义模式后续的timings参数就生效。hdmi_timings这一行是最关键的格式严格按照树莓派官方文档定义水平有效像素、水平同步极性、水平前肩、水平同步脉宽、水平后肩、垂直有效像素、垂直同步极性、垂直前肩、垂直同步脉宽、垂直后肩、垂直同步偏移、是否隔行、像素时钟、宽高比、像素重复。这里的参数对应853x48060Hz的VESA标准时序854是水平有效像素0代表水平同步极性为负20是水平前肩20是水平同步脉宽28是水平后肩加起来水平总像素是854202028922480是垂直有效像素0代表垂直同步极性为负2是垂直前肩2是垂直同步脉宽4是垂直后肩垂直总行数是4802244880和0分别代表垂直同步偏移为0、非隔行扫描27000000是像素时钟27MHz4代表宽高比16:90代表像素重复关闭可能有朋友问这串数字是怎么算出来的像素时钟有个简单的验证公式帧率等于像素时钟除以总像素数和总行数的乘积。27MHz除以922再除以488正好约等于60Hz说明这组时序是自洽的。如果像素时钟配错画面刷新率就会漂移DLP板上视频前端可能锁不住信号。hdmi_drive2是为了让HDMI以HDMI模式输出而不是DVI模式。DLP板的HDMI接收端对DVI信号兼容性一般强制设为HDMI模式后信号质量更稳定。修改完成后执行sudo reboot重启树莓派。有朋友用树莓派5config.txt的路径和参数基本一致。树莓派5的640x480以下特殊启动模式略有不同但自定义timings这条链路在树莓派5上实测同样生效。2.3 验证DLP板被正确识别重启完成系统进入命令行后第一件事就是确认树莓派是否真的按854x48060Hz输出以及系统里framebuffer设备是否正常创建。查看framebuffer设备节点是否存在ls -l /dev/fb0正常情况下应该看到名为fb0的字符设备节点。如果看不到说明内核没有创建framebuffer设备大概率是显示配置有问题或者HDMI没有识别到。用fbset查看当前分辨率和像素格式fbset -fb /dev/fb0输出里会有几何信息和显存格式信息重点看geometry是否显示854x480以及rgba那一行。树莓派在vc4-kms驱动下默认fb0的像素格式可能是RGB565也可能根据配置变成XRGB8888这两种格式在后续显示图片时必须搞清楚。还可以查看framebuffer设备名称cat /sys/class/graphics/fb0/name在树莓派现代系统上通常返回vc4drmfb说明这是DRM/KMS框架创建的fbdev模拟设备。进一步验证画面内容可以先在命令行终端里敲几条命令比如切换到纯TTY看终端文字是否通过DLP板投影出来。如果终端文字清晰投影出来说明整个HDMI链路、时序配置、DMD驱动链路全部正常接下来才能放心操作framebuffer显示图片。3. 深入framebuffer设备3.1 framebuffer在Linux显示栈中的位置Linux显示子系统经过这么多年发展现在是DRM/KMS占据主导地位旧的fbdev接口慢慢退居幕后。但内核为了兼容性保留了framebuffer设备模拟层最简单直接的交互方式就是/dev/fb0这个设备节点。树莓派默认使用了vc4-kms-v3d驱动它整合了GPU显示控制器、HDMI输出、3D渲染等多个子系统。KMS负责管理显示模式、显示平面、连接器这些资源KMS驱动会创建一个fbdev兼容层把/dev/fb0暴露给用户空间。你在用户态往/dev/fb0里写数据fbdev兼容层会把数据转交给DRM的framebuffer扫描输出。这个设计很巧妙的一点是用户空间不需要知道底层是DRM还是老式fbdev驱动统一通过open/read/write/mmap/ioctl操作即可。所以不管树莓派内核版本怎么变只要还有fbdev模拟层这套显示方法就依然有效。framebuffer设备提供几个关键ioctl命令编程前必须熟悉FBIOGET_VSCREENINFO获取可变屏幕信息包括分辨率、像素格式、虚拟分辨率和偏移FBIOGET_FSCREENINFO获取固定屏幕信息包括内存起始地址、行长line_length、显存总大小FBIOPUT_VSCREENINFO设置可变屏幕信息可以用来修改分辨率或者配置双缓冲FBIOPAN_DISPLAY切换显示起始偏移实现画面翻页这些ioctl定义在linux/fb.h头文件里C语言里可以直接引用。3.2 像素格式与显存对齐操作framebuffer最容易翻车的两个点就是像素格式和显存行对齐这里展开细讲。像素格式决定了一个像素在显存里用多少位表示、各颜色分量怎么排列。树莓派fb0常见的格式有两种RGB565和XRGB8888。RGB565用16位表示一个像素高5位红色中间6位绿色低5位蓝色。这种格式省显存16位能表达65536种颜色对人眼来说绝大多数图片都够用。老式fbcon终端默认经常用这种格式。XRGB8888用32位表示一个像素红绿蓝各8位剩下的8位不使用也不透明处理内存里通常按B/G/R/X的顺序排列对应bpp是32。判断当前fb的实际像素格式最直接的方式是看fbset输出中的rgba字段例如rgba 5/11,6/5,5/0,0/16这表示红色5位从bit11开始绿色6位从bit5开始蓝色5位从bit0开始透明度0位从bit16开始这就是标准的RGB565布局。另一种判断方法是写一个探测程序读fb_var_screeninfo的bits_per_pixel、red、green、blue字段自己打印出来。显存行对齐是一个更要命的问题。很多fb设备为了提高内存访问效率并不是每行像素严格按“宽度乘以每像素字节数”布局而是会对齐到某个边界。比如854像素宽、16bpp的显存理论上每行需要854×21708字节但驱动可能把line_length设为1728或者2048多出来的字节就是填充。实际操作中千万别直接用width * 2去计算每行偏移必须从fb_fix_screeninfo的line_length字段读取真实行长。写程序时逐行定位像素位置公式是offset y * line_length x * bytes_per_pixel如果忽略这个对齐图片显示出来会出现斜线偏移或者整图扭曲越靠下的行偏移越严重。3.3 用命令行工具快速点亮在动手写C代码之前先用几个现成工具验证整条链路这样排查问题会快很多。安装fbi工具sudo apt update sudo apt install fbifbi是framebuffer下的图像查看器支持png、jpeg、gif等常见格式会自动缩放适配屏幕分辨率。执行sudo fbi -d /dev/fb0 -T 1 -noverbose test.png这里的-d /dev/fb0指定framebuffer设备-T 1是通知内核切换到VT终端1避免当前终端文字与fbi画面互相干扰。如果看到图片投影出来说明整个显示链路已经通了。fbi有个缺点它会一直占用终端和屏幕退出时需要按回车或者等待设定时间。调试时可以加-t 3让它在3秒后自动退出。还有一种更底层的测试方式直接把原始像素数据用dd写到/dev/fb0里。先借助ImageMagick把图片转成裸RGB565格式sudo apt install imagemagick假设当前fb是RGB565格式用ffmpeg生成裸数据更省事ffmpeg -y -i test.png -vf scale854:480,formatrgb565 -f rawvideo /tmp/fb.raw然后写入framebuffersudo dd if/tmp/fb.raw of/dev/fb0 bs1024 count480如果一切顺利DLP板应该投影出完整图片。dd这种方式写起来简单粗暴但要求raw数据尺寸和fb0的显存布局完全一致一旦有行对齐差异图片底部会出现错位。所以这个命令只能作为临时验证正式项目还是要写程序按line_length逐行处理。4. 自己动手写framebuffer显示程序4.1 用C直接操作/dev/fb0的完整流程命令行工具能点亮但真正在项目里用起来还是得自己写代码。用C操作framebuffer的流程非常固定打开设备、获取信息、内存映射、写像素、清理退出。下面这段程序演示了如何在屏幕指定位置填充一块颜色区域是framebuffer编程的最小模板#include stdio.h #include stdint.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include sys/mman.h #include linux/fb.h int main(int argc, char *argv[]) { int fb_fd; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; fb_fd open(/dev/fb0, O_RDWR); if (fb_fd 0) { perror(open /dev/fb0); return 1; } if (ioctl(fb_fd, FBIOGET_VSCREENINFO, vinfo)) { perror(FBIOGET_VSCREENINFO); return 1; } if (ioctl(fb_fd, FBIOGET_FSCREENINFO, finfo)) { perror(FBIOGET_FSCREENINFO); return 1; } printf(display: %dx%d, %d bpp\n, vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); printf(line_length: %d bytes\n, finfo.line_length); long screensize vinfo.yres_virtual * finfo.line_length; uint8_t *fbp mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); if (fbp MAP_FAILED) { perror(mmap); return 1; } int bytes_per_pixel vinfo.bits_per_pixel / 8; int x, y; /* 在左上角画一个100x100的红色方块 */ for (y 0; y 100; y) { for (x 0; x 100; x) { long offset y * finfo.line_length x * bytes_per_pixel; if (vinfo.bits_per_pixel 16) { /* RGB565 */ uint16_t pixel (31 11) | (0 5) | 0; *((uint16_t *)(fbp offset)) pixel; } else if (vinfo.bits_per_pixel 32) { /* XRGB8888注意栈上字节序 */ uint32_t pixel (0xFF 16) | (0 8) | 0; *((uint32_t *)(fbp offset)) pixel; } } } munmap(fbp, screensize); close(fb_fd); return 0; }这段代码核心逻辑很好理解。打开/dev/fb0后通过两个ioctl拿参数mmap把显存映射到用户空间地址接下来就是纯粹的内存写入。画红色方块是为了验证像素格式是否正确如果显示出来的方块颜色不对说明RGB分量偏移没有匹配当前fb格式。还有一个细节很多新手的代码直接把xres当屏幕宽度来算偏移忽略yres_virtual和xoffset/yoffset。在简单场景下xoffset和yoffset都是0但一旦配置了双缓冲或者pan显示这两个值就会变成非零偏移必须把坐标加上offset再换算内存位置。4.2 图片解码与像素格式转换纯C代码直接显示图片如果不想引入复杂的图像解码库可以只支持BMP格式。BMP没有压缩或者只有简单RLE压缩头部结构固定解析起来很轻松。更通用的做法是用libpng或者libjpeg解码但依赖库会多一点。对于快速原型和验证项目我更喜欢用Python加numpy和Pillow来做图片解析和格式转换逻辑清晰而且改起来快。下面这个脚本把PNG图片直接写到framebuffer上#!/usr/bin/env python3 import sys import numpy as np from PIL import Image FB_DEV /dev/fb0 IMAGE sys.argv[1] if len(sys.argv) 1 else test.png img Image.open(IMAGE).convert(RGB).resize((854, 480)) arr np.array(img) # 转换为RGB565小端格式 r (arr[:, :, 0].astype(np.uint16) 3) 11 g (arr[:, :, 1].astype(np.uint16) 2) 5 b (arr[:, :, 2].astype(np.uint16) 3) rgb565 (r | g | b).astype(u2) data rgb565.tobytes() with open(FB_DEV, wb) as fb: fb.write(data)这个脚本假设fb是RGB565格式且每行显存长度就是854乘2字节。如果想要处理line_length对齐需要从fbset的输出里读取实际的行长再逐行写入。逐行写入时先用os.pread定位文件偏移或者用seek跳转import os line_length 1728 # 实际值从fbset读出来 width 854 height 480 with open(FB_DEV, wb) as fb: for y in range(height): row_start y * width * 2 row_end row_start width * 2 row_data data[row_start:row_end] fb.seek(y * line_length) fb.write(row_data)把line_length从fbset里读出来填进代码这个脚本就在不同驱动配置下都能稳定工作。Python脚本虽然方便但性能有限。如果要在树莓派上做连续帧动画或者实时视频显示会频繁产生GIL开销和系统调用建议直接用C/C配合libdrm或者手动mmap操作显存。树莓派的GPU能力虽然有限但854x480分辨率的RGB565视频用C程序双缓冲完全可以跑到60帧瓶颈主要在图像解码和上层应用逻辑上。4.3 双缓冲与画面撕裂单缓冲在显示静态图片时完全够用但一旦做动画或者视频播放就会遇到画面撕裂。撕裂的本质是写入显存和扫描输出同时进行上半屏已经扫出新内容下半屏还在扫旧内容看起来像画面被水平撕开。最简单的解法是双缓冲加pan display在虚拟显存里分配两倍高度的缓冲区一个用于后台绘制一个用于前台显示切换时用ioctl把显示起点跳到另一块缓冲区首地址。用fb_var_screeninfo配置虚拟分辨率实现双缓冲代码思路如下struct fb_var_screeninfo vinfo; /* 设置虚拟分辨率高度设为实际高度的2倍 */ vinfo.xres 854; vinfo.yres 480; vinfo.xres_virtual 854; vinfo.yres_virtual 960; ioctl(fb_fd, FBIOPUT_VSCREENINFO, vinfo); /* 写后台缓冲时y坐标加上480偏移 */ draw_to_buffer(fbp, 0, 480); /* 切前台显示到后台缓冲 */ vinfo.yoffset 480; ioctl(fb_fd, FBIOPAN_DISPLAY, vinfo);每次把新帧画到后台缓冲区然后设置yoffset跳到上一帧所在的缓冲区位置一瞬间完成切换。切换过程中不会出现撕裂因为扫描输出永远只读取当前显示的缓冲区。树莓派使用DRM/KMS驱动时fbdev模拟层的双缓冲行为可能与老式fbdev驱动有些差异但FBIOPAN_DISPLAY这个ioctl在多数内核版本里依然可用。如果发现不支持只能走libdrm层面去操作plane和framebuffer那套接口更复杂但更稳定。5. 踩坑实录常见问题与排查技巧5.1 分辨率不对、黑屏、无信号怎么查这套方案里我遇到最多的问题排名第一就是“DLP板上完全没有画面”。排查顺序从硬件到软件不要跳步。第一步检查DLP板供电。看板上的电源指示灯是否亮LED驱动部分是否在工作。很多EVM板如果供电不足只有控制器工作但LED不亮投影出来就是一片黑看起来像是没信号。第二步检查HDMI线材。mini-HDMI线质量参差不齐有的线序不全导致DCC通道不通树莓派读不到EDID强制热插拔也救不回来。手头有示波器可以测一下TMDS信号没示波器就换一根线试试。第三步确认config.txt配置生效。执行vcgencmd get_config hdmi_timings vcgencmd get_config hdmi_group vcgencmd get_config hdmi_mode如果get_config返回空值说明config.txt里的参数根本没有被加载。常见原因是文件路径写错或者格式错误树莓派5的固件对hdmi_timings某些字段的格式要求更严格。第四步查看内核日志dmesg | grep -i hdmi dmesg | grep -i vc4看有没有HDMI协商失败、KMS驱动初始化错误等信息。有时候树莓派检测不到显示器会退回到复合视频输出或者禁用HDMI日志里会有明确提示。有一个细节如果把树莓派连接到DLP板的同时又接了其他显示器做调试要注意fb0对应哪个显示器。多个连接器同时使能时fb0可能是主显示输出也可能是第一个被枚举的连接器不一定是你想要的DLP板。这种情况下用cat /sys/class/drm/card0-*/status逐一查看连接器状态或者在config.txt里显式禁用不用的HDMI口。5.2 颜色异常、花屏、偏移的修正颜色不对通常就是像素格式不匹配。用fbset看到是RGB565但图片数据是按RGB888处理的画面就会偏色甚至变成彩色噪点。我习惯写一个纯色测试程序依次输出红绿蓝纯色肉眼判断RGB通道是否正常映射。如果红色看起来像蓝色绿色正常往往不是字节序问题而是RGB分量的bit位置配置不对。fb_var_screeninfo里的red/green/blue字段告诉我们每个颜色分量从哪一位开始、占几位。写程序时要根据这些字段动态生成像素值而不是写死RGB565的位移。花屏或者图片整体偏移优先怀疑行对齐问题。用dd方式直接写入最容易暴露这个问题。如果图片上部分正常、越往下越偏那就是line_length和实际宽度乘字节数不一致。可以在程序里把line_length打印出来和期望值对比差多少心里就有数了。还有一种情况是终端文字覆盖在图片上。系统默认启动后会有一个getty进程占用TTYTTY的text console会映射到framebuffer上。即使你写了图片光标和终端提示符还是会盖在上面闪。解决办法是在cmdline.txt里添加fbconmap:0或者干脆用chvt切换到空TTYsudo chvt 2如果用了fbi-T 1参数已经帮你切换了VT但自己写程序时就要自己处理VT切换或者关掉console blanking。5.3 进阶玩法把DLP板的控制接口利用起来除了HDMI显示链路DLPDLCR230NPEVM板上还有一个micro-USB接口通过这个接口可以访问DLPC3436的寄存器控制DMD的启动模式、LED电流、色序参数等。树莓派连接这个USB口后Linux会识别出一个USB串口设备一般是/dev/ttyACM0可以通过串口命令配置DLP板。TI官方提供了一套DLP EVM GUI软件通常是Windows版本的Linux下操作寄存器可以用串口直接读写。DLPC3436支持I2C和SPI接口配置USB只是承载层真正的控制总线是接到DLPC3436的I2C或者SPI上。如果想在Linux下写配置工具需要查DLPC3436的编程手册通过USB转I2C桥接芯片发送命令。这个控制通道可以做的事情很多调整投影亮度、切换LED使能顺序、读取DLP板温度状态、配置新的输入源模式。如果只是显示图片不碰这些配置也能跑但一旦涉及到LED电流控制或者特殊同步信号就必须走控制通道。还有个好玩的方向是用树莓派的GPIO控制DLP板的电源和复位时序实现按需开关投影。在低功耗嵌入式设备里DMD上电到画面稳定输出需要一段初始化时间上位机需要精确控制这个上电时序不能让DLP板和树莓派同时上电否则可能出现DMD微镜状态不确定的问题。这个需要用树莓派的GPIO接一个电源控制MOS管开关延时一段时间后再使能DMD。我自己实际用下来的体会是framebuffer这条路对于固定分辨率的显示应用非常合适简单直接、依赖少、稳定性高。但如果要做复杂UI交互、视频硬件解码、多窗口合成那就应该老老实实用DRM/KMS或者直接上桌面系统不要硬在framebuffer里折腾。选技术方案从来不是越底层越好而是看你的应用瓶颈到底在哪。DMD投影这种场景瓶颈在图像数据准备和时序控制上framebuffer正好把显示路径降到最短所以它是最优解。
返回列表