恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
MTK显示架构演进:从MDP到DDP的深度解析
首页
资讯中心
/
MTK显示架构演进:从MDP到DDP的深度解析
MTK显示架构演进:从MDP到DDP的深度解析
发布时间:2026/9/29 18:39:52
说到MTK的显示架构很多做底层驱动或系统优化的朋友一定不陌生。早几年在MT6589、MT6753这些平台上追显示丢帧、花屏问题入口基本都是MDP相关的那一套寄存器到了MT6785、MT6895这类新平台再看代码和调试节点已经是DDP的天下了。这个从MDP到DDP的变化不是简单的换个名字而是MTK显示子系统在数据通路、模块划分和电源管理上的一次系统性重构。这篇文章我想把这条演进路线完整拆一遍先说明MDP和DDP分别解决什么问题再展开新架构里OVL、RDMA、DSC这些模块是怎么协作的接着给出一套实操验证方法最后聊聊我们在维护老平台和适配新平台时踩过的一些坑。内容偏底层但我会尽量用通俗的类比和实际日志来讲适合刚接触MTK平台的驱动开发者也适合做上层系统优化的同学用来建立全局认识。1. 为什么显示架构需要一次“换心”从MDP到DDP的演进动因很多朋友第一次接触MTK显示子系统时会被mdp、ddp、mtkfb、disp这一堆缩写搞晕。其实它们代表的是两代设计思路。早期MTK把显示相关的大部分任务收敛在一个叫MDP的模块里全称可以理解为Media Data Path或Main Display Path负责把内存中的图像数据搬到屏幕。这个设计在WVGA、720P时代完全够用但到了FullHD高刷、多摄像头同时预览、折叠屏多屏输出之后单靠一个MDP去处理所有数据流就非常吃力。1.1 老架构MDP解决什么问题MDP时代的设计核心是“单通路优先”。它的任务很纯粹从一个或者少数几个图层源读像素做必要的格式转换然后通过显示接口送到LCD/HDMI。你可以把它想成一根很粗的管子图像数据从这头进去从另一头出来中间只做缩放和裁剪这类基本操作。这套架构最大的优点是简单、可控。寄存器数量少状态机清晰出问题时直接看MDP中断状态就能定位。早期MTK平台上Camera preview和Video playback的默认通路基本都是走MDP因为它不需要复杂的合成逻辑只需要把视频层叠在UI层上输出就行。但缺点也非常明显第一图层数量一旦超过MDP能承载的上限通常只有2到3层多出来的图层就必须CPU/GPU合成到内存再送显功耗高、延迟大第二MDP的带宽调度能力弱面对高分辨率高刷新率时行场同步很容易被内存访问竞争干扰出现屏幕一边刷一边顿的现象第三扩展多屏输出非常笨拙因为整个MDP通路天然是单显示接口的。1.2 新架构DDP到底新在哪里DDP也就是Display Data Pipeline是MTK在进入4K/高刷时代后重构的显示数据流方案。它不是把MDP换个名字而是把原来“一个大模块”拆成了若干个小而专的硬件引擎再通过一个可编程的流水线把它们串起来。每个引擎只干一件事OVL做图层叠加RDMA负责从内存读像素WDMA负责把结果显示写回内存AAL/GAMMA做色彩和亮度调节DSI/DP负责物理链路输出。这套架构最大的变化是“拼接式流水线”。不同使用场景可以组装不同引擎组合比如普通UI显示是OVL-RDMA-DSI而截图功能是WDMA独立把当前画面写回内存视频增强场景可以额外加入PQPicture Quality模块。每个模块通过标准接口互联数据流动方向和时机由DDP管理器统一控制和MDP那种“一根管子走到底”完全不一样。从软件层面看DDP催生了更清晰的驱动分层底层是disp_*各个引擎驱动中间是DDP manager负责时钟、电源、帧同步的统筹上层才对接mtkfb或 DRM/KMS。这就是为什么新平台看代码时处处都能看到DDP_OVL、DDP_RDMA这样的抽象宏而老平台则是一大坨MDP_*寄存器直接裸操作。对做系统优化的人来说这意味着我们可以更精确地定位到每一帧的瓶颈出在哪个引擎上而不是靠猜。2. MTK显示数据通路的核心模块与工作流要理解DDP必须把数据通路的几个核心模块先吃透。我平时排查问题最常打交道的四个模块是OVL、RDMA、WDMA和DSI Display。下面我用一条HDMI输出的场景来串这四者解释数据从内存到屏幕的完整路径。2.1 从OVL到RDMA数据如何从内存到屏幕上游App通过SurfaceFlinger把图层提交给HWCHardware ComposerHWC经过策略比较决定底层图层还是由硬件合成。硬件合成的入口就是OVL。OVL模块接收多个图层输入每个输入channel可以配置不同的像素格式、起始地址、宽高和透明度。OVL内部做alpha blending和z-order排序最终合成一张完整的画面。注意OVL虽然强大但它的layer数量是有限的。中端平台通常是4层旗舰平台可能到6层。如果UI图层超过这个数量HWC会把其中一部分图层先由GPU合成再作为一个图层送入OVL这就是我们常说的GPU合成与硬件合成的临界点。排查性能问题时要先确认当前帧是不是越过了这个点。合成完成后数据还在“引擎内部”接下来需要RDMA读取结果。更准确地说OVL的结果会直接交给后端模块而RDMA的作用是把画面数据从内存或者前端模块搬运到显示后端。RDMA的名字是Read DMA它的核心职责是保证按像素时钟精准地从DDR搬数据并且做好行缓冲避免接口等数据。一些平台上RDMA还承担格式转换比如ARGB8888转RGB565这能减少后端接口的带宽压力。然后数据到达DSI或DP Transmitter。DSI在手机上是主流分D-PHY和C-PHY通常有2到4条lane。这部分是物理层关注的是时序参数比如HSA、HBP、VFP、VBP。如果这些参数配错屏幕会直接花屏或黑屏而且这类问题不太容易从内核日志看到得借示波器量。2.2 模块之间的握手帧同步与命令队列DDP里的多个引擎不是各跑各的它们通过帧同步机制Frame Synchronization紧密协作。每一帧开始主时钟源产生VSYNC信号OVL开始读图层RDMA同步开始搬数据DSI在TETearing Effect信号到来后启动输出。如果某个引擎没跟上就会出现tearing或stutter。MTK为了解决引擎速度不一致的问题给每个引擎加了shadow register和command queue。驱动先把所有寄存器配置写到shadow register里在VSYNC触发点统一加载到硬件寄存器。这样保证一帧内的所有配置是原子生效的不会出现“RDMA已经是新配置OVL还在跑旧配置”的半更新状态。调试时如果怀疑某个引擎配置没生效建议先看它的shadow register状态位确认是否处于pending状态。另一个值得注意的机制是DDP的clock gating和bus QoS。每个引擎可以独立开关时钟没有画面输出时自动gate掉。同时DDP会向内存总线申请QoS带宽确保和其他子系统尤其GPU和Camera竞争DDR时显示通路有足够优先级。这条设计比MDP时代精细得多但也带来一个新问题QoS配置不合适反而会导致抢带宽这个我们后面实操部分会讲。3. 新旧架构切换带来的实际变化这一章聊架构演进带来的可感知变化。带宽管理、功耗、多屏能力是最明显的三个维度。3.1 带宽与功耗的权衡MDP时代显示路径的带宽基本“吃满”。因为它要在有限层面上把所有图层数据读一遍再混合输出一旦图层多了带宽倍增。比如1080p30fpsRGBA8888一条显示通路带宽大约1920×1080×4×30≈248.8MB/sMDP勉强扛住到1080p60fps就接近500MB/s再加上GPU写回DDR压力非常大。DDP架构虽然也是要读图层但它通过更智能的layer裁剪和像素格式压缩来降低带宽。最典型的是AFBCArm Frame Buffer Compression的支持UI图层在SurfaceFlinger阶段压缩OVL读取时直接解压合成。这样同样一张1080p60fps的画面DDR到显示引擎的带宽可以减少一半以上。功耗也随之下降毕竟显示通路在DDR总线上的读操作是耗电大户。当然DDP也带来额外的功耗来源多个引擎的独立时钟树、总线和QoS电路。如果驱动不做动态电源管理一直让所有引擎保持最高时钟那功耗反而比MDP更差。所以新平台的显驱几乎都把suspend/resume和buffer状态挂钩只有帧数超过阈值时才会把OVL/RDMA全部推到最高性能档。3.2 多屏与折叠屏时代的新能力MDP时代做双LCD或者LCDHDMI扩展很痛苦需要额外挂一整套外部显示控制器两个屏幕之间没法共享合成结果。DDP架构直接用两条display pipeline可以在每个pipeline里配置不同的OVL和RDMA资源然后由同一个DDP manager做时钟和帧同步协调。比如折叠屏的内屏和外屏通常就是两个DSI接口接到同一个DDP上。铰链状态切换时系统把显示内容从一个pipeline切换到另一个动态改变OVL的图层配置和亮度gamma值实现平滑过渡。这种场景在MDP下几乎是不可想象的因为音频/传感器/显示要同步切换没有一个统一的数据通路管理器很难做。DDP还引入了secure display flow。在DRM PlayReady或Widevine L1播放场景下视频内容不允许被CPU/GPU读取MDP在这个问题上很吃力因为它需要绕过系统内存做受保护路径。DDP则支持将OVL的某个图层标记为secure直接由显示硬件从受保护内存读取并合成不走普通DDR。这个能力对现在的流媒体体验至关重要。4. 实操在MTK设备上怎么快速识别当前显示架构与排查显示问题理论聊完了讲点落地的东西。作为系统工程师拿到一台MTK设备第一件事是搞清楚它跑的是MDP还是DDP以及各个引擎的配置情况。下面是我常做的一套检查流程和问题排查方法。4.1 通过内核节点和日志定位MDP/DDP版本MTK平台的内核日志非常啰嗦但也很诚实地暴露了显示架构。连接设备后先做三件事adb shell dmesg | grep -iE mdp|ddp|disp_ovl|disp_rdma adb shell cat /sys/kernel/debug/mtkfb/0 adb shell ls /sys/class/video/第一行是看驱动初始化时打印的版本信息。如果是DDP平台你会看到DDP开头的模块初始化序列比如[DDP_OVL]、[DDP_RDMA]如果是老MDP平台基本只能看到MDP和MTKFB相关的报错。第二行是查看Framebuffer当前的显示参数和输出路径第三行是历史遗留的video设备节点有些老项目会在/sys/class/video/下暴露FBI0、VBI0等节点新DRM/DDP平台则更多走/sys/kernel/debug/dri/0/。注意新平台如果开了DRM/sys/class/video可能完全不存在。不要只靠几个路径判断架构最保险的是看dumpsys SurfaceFlinger里的HWC v2/v4能力以及内核config里是否有CONFIG_MTK_DISP相关配置。如果要看当前正在运行的显示流水线可以读DRM调试节点adb shell cat /sys/kernel/debug/dri/0/state adb shell dumpsys displaystate文件会列出每个plane的关联、格式、尺寸以及fb id能直观看到硬件图层被分配给了哪几个plane。结合SurfaceFlinger的图层信息就能判断当前UI帧是硬件合成还是GPU合成。4.2 常见显示问题排查与优化建议DDP架构下问题定位的路径更清晰但坑也不少。我整理了几类高频问题附上排查思路第一类花屏或闪屏。优先查DSI时序和时钟尤其是clk_get_rate是否低于pixel_clock * 1.05。DDP平台如果RDMA读不到数据也会闪所以再查RDMA的underrun中断计数adb shell cat /sys/kernel/debug/mtkfb/0 | grep -i underrun如果underrun一直增加说明DDR带宽不足或QoS配置太低需要调高RDMA的QoS level。第二类固定帧率掉到一半比如60Hz变成30Hz。很大概率是DDP进入低功耗模式帧率桶没对上。检查系统是否用了PSMPanel Self Refresh或者CABC这两个特性在检测到静态画面时会降低刷新率。排查时可以临时关闭adb shell settings put global low_power_backlight 0 adb shell dumpsys display | grep -iE refresh rate|display mode第三类多屏串联时副屏卡顿。这种问题多半是DDP manager没有给副屏分配独立时钟域导致副屏和主屏争抢RDMA带宽。可以查看两个pipeline的rate是否独立如果共用就调整dts里的clock property给副屏单独一个PLL。下面这张表是我常用的快速对照表现象可能原因快速验证方法屏幕闪烁但日志干净DSI时序余量不足示波器量HBP/VFP或加大porch参数观察滚动时字体变形OVL layer数量超限走到GPU合成dumpsys SurfaceFlinger看合成类型屏幕局部一闪而过RDMA underrun查underrun中断计数亮暗跳变AAL/GAMMA表刷新查看disp_aal寄存器状态待机唤醒黑屏DDP pipeline 没正常resumedmesg4.3 手写一个DDP带宽估算小脚本排查带宽问题最基础的是先估算理论带宽。举个例子一块1080p60Hz的屏幕像素格式RGB888DDP读取图层时如果做双图层合成那么OVL需要读两次全屏数据RDMA输出一次全屏数据。读写总带宽大约是$$(1920 \times 1080 \times 3 \times 60) \times (2 1) 1119.7MB/s$$再考虑AFBC压缩到原来的一半读取部分大约减半最终大约746MB/s。这个数字要和DDR控制器带宽上限对比。现在中端DDR4的带宽通常有12.8GB/s以上理论上不是瓶颈但如果有GPU写回、Camera ISP同时抢带宽就需要通过CPU的CCI或AXI QoS设置给显示通路预留带宽。我平时写一个很小的Python脚本用来快速估算多种格式下的带宽def calc_bandwidth(width, height, fps, bpp, layers, compression_ratio1.0): frame_bytes width * height * bpp // 8 raw_bandwidth frame_bytes * fps * (layers 1) # read layers write output effective_bandwidth raw_bandwidth / compression_ratio return effective_bandwidth / 1024 / 1024 # MB/s print(calc_bandwidth(1920, 1080, 60, 32, 2, compression_ratio1.0)) print(calc_bandwidth(1920, 1080, 60, 32, 2, compression_ratio2.0))跑一下就能发现在4K60Hz、4图层、RGBA8888的场景下哪怕是AFBC压缩带宽压力也会接近1.4GB/s。如果设备在发热降频时DDR频率被压低就很容易触发underrun。这就是为什么新平台都强制建议做AFBC或类似格式压缩。5. 从MDP到DDP给我们做系统优化的三点启示按说我讲到这里可以直接收尾但作为实际在MTK平台踩过不少坑的人还是想说几句体会。如果你现在还在维护老MDP平台或者刚切到DDP新平台下面三点应该能帮上忙。5.1 老平台维护MDP还能再战吗从功能上讲老MDP平台只要不做高帧率、不多屏高清输出日常使用仍然很稳。但有一个隐蔽问题随着Android版本升级SurfaceFlinger默认会增加一些新图层比如圆角剪切、HDR色调映射这些图层如果HWC不支持就会在HWC层被强制拉回MDP合成导致性能不升反降。维护老平台时建议在HWC配置里明确声明支持的合成模式宁可让GPU多干活也不要让MDP在极限状态下反复重启通路。MDP的重启很伤画质会出现明显的一帧闪黑。5.2 新平台适配拿到DDP之后先做什么拿到一台DDP新平台的设备我会建议从上电开始先做三件事第一抓一份完整的显示初始化dmesg并保存这个基线日志比任何文档都准第二把每个引擎的独立clock全部列出来确认哪些是在运行时可以动态开关的第三验证low power mode的进入退出路径确保在屏保或者AODAlways On Display场景下OVL和RDMA可以彻底gate掉只保留最小的DSI-on到家。这些做完后面调试帧率、功耗会事半功倍。5.3 显示架构之外MTK与高通的对比视角顺带提一句很多人喜欢拿MTK和高通比较。从显示架构看两者方向相同都在做模块化流水线和带宽QoS但实现细节差异很大。高通的显示子系统叫MDSS在Linux内核里通过DPU驱动管理和MTK的DDP类似都是多引擎组合。区别在于高通更早把显示驱动并入DRM框架而MTK的DDP目前还保留不少私有接口适配时要花一些精力把私有调用桥接到标准KMS。理解这一点就不会在换平台时对着代码愣神了。我个人在实际工作中最大的感触是架构演进解决的是“能做什么”的问题而真正的差距在“怎么用好它”。MDP到DDP这条路表面是模块更丰富、带宽更高本质是把复杂性从硬件端子转移到了软硬协同的管理层。无论平台怎么变搞清楚每一帧数据从哪来、在哪个引擎停留多久、最终如何送到屏幕永远是显示链路调试的核心。希望这篇梳理能让你少走些弯路。