尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

6. Plane驱动实现:mtk_plane.c分析、Overlay硬件单元、格式转换与缩放、Alpha混合

6. Plane驱动实现:mtk_plane.c分析、Overlay硬件单元、格式转换与缩放、Alpha混合 6.1 mtk_plane.c 核心结构先看代码骨架。MTK的Plane驱动核心文件就是mtk_plane.c。它主要做了三件事注册Plane到DRM框架实现atomic_check和atomic_update回调管理Overlay硬件资源我贴一段关键的结构体定义struct mtk_plane { struct drm_plane base; struct mtk_plane_state *state; struct mtk_ddp_comp *ddp_comp; int idx; bool enabled; };嗯这里要注意ddp_comp这个指针。它指向的是显示流水线里的具体硬件模块。每个Plane都绑定了一个DDP组件说白了就是硬件Overlay单元。6.2 Overlay硬件单元MTK8678的Overlay单元我直接说结论它支持4个图层叠加。每个图层都有独立的寄存器组用来配置源地址、目标尺寸、格式、透明度等。我在项目中遇到过一个问题客户要求同时显示主界面、画中画、悬浮按钮和状态栏。结果发现第四个图层死活出不来。查了半天原来是某个Overlay单元被其他模块占用了。嗯这玩意儿是共享资源用之前得先申请。Overlay硬件单元的主要能力支持RGB和YUV格式输入支持1x到4x缩放硬件scaler支持逐像素Alpha混合支持全局Alpha整个图层半透明关键寄存器OVL_CON控制寄存器、OVL_SRC_ADDR源地址、OVL_SRC_SIZE源尺寸、OVL_DST_SIZE目标尺寸、OVL_ALPHA透明度控制。6.3 格式转换与缩放格式转换这块说白了就是硬件帮你做颜色空间转换。比如视频流通常是NV12YUV但屏幕是RGB。Overlay硬件内部有个CSCColor Space Converter模块自动帮你转。我曾经踩过一个坑用NV12格式播放视频结果颜色偏绿。查了三天发现是CSC矩阵配置错了。MTK的CSC矩阵有标准模式和宽色域模式默认是标准模式但视频源是BT.2020宽色域。改一下寄存器就好了。缩放就更直接了。硬件scaler支持双线性插值和最近邻插值。我建议视频播放用双线性画质好游戏UI用最近邻速度快看一段配置代码static void mtk_plane_setup_scaler(struct mtk_plane_state *state) { struct mtk_rect src state-src; struct mtk_rect dst state-dst; // 计算缩放比例 u32 hscale (src.width 12) / dst.width; u32 vscale (src.height 12) / dst.height; // 写入硬件寄存器 writel(hscale, OVL_HSIZE); writel(vscale, OVL_VSIZE); }这里 12是定点数表示法保留小数精度。说白了就是硬件只认整数但我们要做亚像素精度控制。6.4 Alpha混合Alpha混合是Plane的灵魂。没有它图层就是硬叠互相遮挡。有了Alpha才能实现半透明、淡入淡出、阴影效果。MTK的Overlay支持两种Alpha模式模式描述适用场景全局Alpha整个图层统一透明度悬浮窗、状态栏逐像素Alpha每个像素有自己的Alpha值带透明通道的PNG、视频字幕混合公式很简单输出 前景 * Alpha 背景 * (1 - Alpha)但硬件实现起来有讲究。我记得有一次做画中画功能主画面和子画面叠加时边缘出现黑边。原因是子画面的Alpha通道没有做预乘Premultiplied Alpha。避坑指南我曾经在配置Alpha混合时忘记设置OVL_CON寄存器的PREMULTI_EN位。结果半透明区域全是黑色锯齿。解决办法很简单把源数据做预乘或者硬件开启预乘模式。看一段Alpha配置代码static void mtk_plane_set_alpha(struct mtk_plane_state *state) { u32 alpha state-base.alpha; // 0-255 u32 premulti state-base.pixel_blend_mode; // 配置全局Alpha writel(alpha, OVL_ALPHA); // 配置混合模式 if (premulti DRM_MODE_BLEND_PREMULTI) set_bit(OVL_CON_PREMULTI_EN, OVL_CON); else clear_bit(OVL_CON_PREMULTI_EN, OVL_CON); }这里DRM_MODE_BLEND_PREMULTI是DRM框架定义的混合模式。说白了就是告诉硬件你的Alpha是预乘过的还是没预乘的。搞错了画面就崩。6.5 实战经验总结最后我分享几个实际调试中的经验先确认硬件资源Overlay单元数量有限用之前检查mtk_ddp_comp_get是否成功格式转换要匹配源格式和目标格式的CSC矩阵必须对应否则颜色失真缩放性能要评估4K分辨率下做2x缩放带宽压力很大。我建议用perf工具监控DDR带宽Alpha混合顺序多个图层叠加时从底层到顶层依次混合。顺序错了半透明效果就乱套警告千万不要在中断上下文里配置Plane寄存器。我曾经这么干过结果系统直接死锁。Plane配置必须在atomic_update回调里完成而且要用spin_lock保护。好了Plane驱动这块就聊到这儿。说白了它就是显示流水线里的“图层管理员”。你只要把源地址、尺寸、格式、Alpha值告诉它它就能帮你把画面叠到屏幕上。下一章咱们聊聊CRTC驱动那个更刺激——它管的是整个显示时序。
返回列表