当前位置:首页 > 汽车电子 > 汽车电子
[导读]车机多窗口不是把导航Activity、音乐Activity、仪表View叠一起就完事。座舱屏最怕两件事:音乐悬浮窗盖住车速,导航刷新把仪表帧率拖垮。正确做法是把显示拆成硬件图层(Plane/Layer),按信息优先级定Z-order,由DPU/Weston/SurfaceFlinger做合成,应用只提交各自Surface,不互相覆盖。


车机多窗口不是把导航Activity、音乐Activity、仪表View叠一起就完事。座舱屏最怕两件事:音乐悬浮窗盖住车速,导航刷新把仪表帧率拖垮。正确做法是把显示拆成硬件图层(Plane/Layer),按信息优先级定Z-order,由DPU/Weston/SurfaceFlinger做合成,应用只提交各自Surface,不互相覆盖。

一、信息优先级决定图层归属

先定层级,再谈布局:

P0 仪表层:车速、转速、ADAS告警、转向提示 → 独占底层硬件plane,禁止被覆盖

P1 导航层:中控地图、路线卡片、AR箭头

P2 媒体层:音乐卡片、专辑封面、歌词

P3 通知层:来电、消息Toast、空调弹窗

Overlay层:ADAS碰撞预警、确认弹窗,临时置顶

仪表屏和HUD归安全域,媒体窗口可以“飞屏”过去,但只能占预留信息区,不能压车速数字。

二、窗口对象与Z-order管理

Wayland/ivi-shell思路抽象成结构体:

typedef enum {

   LAYER_CLUSTER = 0,   // P0

   LAYER_NAV,          // P1

   LAYER_MEDIA,        // P2

   LAYER_NOTIFY,       // P3

   LAYER_OVERLAY       // 告警置顶

} win_layer_t;


typedef struct {

   int id;

   win_layer_t layer;

   int z;              // 同层内顺序

   rect_t rect;

   rect_t dirty;       // 仅刷新变化区

   uint8_t alpha;

   uint8_t visible;

   uint32_t surface_id;

} win_t;


win_t wins[MAX_WIN];

合成前先过仲裁:

int compose_priority(win_t*a, win_t*b){

   if(a->layer != b->layer) return a->layer - b->layer;

   return a->z - b->z;

}

音乐窗口layer=MEDIA,仪表底图layer=CLUSTER,Z-order天然隔开;就算音乐飞到仪表区,也只允许进“副信息槽”,主车速区在合成阶段裁剪掉。

三、DPU硬件合成优先

别把所有图层丢给GPU合成,车机平台应该走overlay plane:

仪表底图 → DPU base layer

导航地图 → overlay plane 0

音乐卡片 → overlay plane 1

告警条 → overlay plane 2(最高)

超出plane数量才GPU fallback合成

/* Weston/DRM思路 */

drm_plane_assign(PLANE_BASE, cluster_surf);

drm_plane_assign(PLANE_OVL0, nav_surf);

drm_plane_assign(PLANE_OVL1, media_surf);

drm_plane_set_zorder(PLANE_OVL1, PLANE_OVL0);

规则:

视频/地图走YUYV/UBWC,别用线性RGBA硬搬,带宽炸

静态壁纸合成一次底图缓存,不每帧重画

歌词滚动只更新文字脏区,不动地图

音乐封面切换才重传surface,平时不动

四、VSync+Fence防撕裂

多窗口同屏必须绑同一个垂直同步:

所有surface按VSync周期提交

写完成用fence/acquire fence,别CPU等GPU

present()一次出整屏,避免中控显示“左转”、仪表还停“直行”

drm_wait_vblank(fd, &vbl);

compositor_commit(layers);   // 一次atomic commit

跨屏同步(中控+仪表+HUD)用统一VSync源或主屏时钟分发,延迟要求一般≤50ms。

五、状态同源:别各屏各算一份

多屏最容易出“仪表歌名旧、中控已切歌”。正确是单一数据源:

typedef struct {

   int speed_kmh;

   uint8_t gear;

   nav_cmd_t nav;

   media_state_t media;

} vehicle_state_t;


vehicle_state_t g_state;   // 服务层更新


/* 各窗口订阅同一份 */

cluster_update(&g_state);

nav_update(&g_state);

media_update(&g_state);

CAN/以太网来的车速、方控切歌、导航指令都先写g_state,渲染线程按当前帧读。

六、行车场景动态降级

驾驶模式切换时重构层级:

行车中:媒体图层降透明度、歌词关、动画关

倒挡:后视摄像头层强插P0之上

ADAS告警:Overlay层置顶,音乐让位

停车:音乐卡片可全屏、帧率恢复

if(drive_mode == DRIVE){

   set_layer_visible(LAYER_MEDIA_LYRIC, 0);

   lower_fps(LAYER_MEDIA, 10);

}

七、落坑清单

音乐View直接盖仪表Speed→安全信息被挡

所有窗口GPU合成→DPU闲置、发热掉帧

每帧整屏重绘→地图卡、歌词抖

中控仪表各维护一份状态→显示不同步

不绑VSync→跨屏撕裂

歌词动画行车常开→分散注意力

overlay plane超数量不fallback→合成失败黑屏

悬浮窗z-index写魔法数→层级冲突

倒车摄像头不抢顶层→被导航盖住

媒体飞屏占满仪表→车速区被挤

八、落地顺序

定层级:Cluster/Nav/Media/Notify/Overlay

仪表底图走base plane,媒体走overlay

窗口对象带layer+z+dirty,合成前仲裁

音乐飞屏只进副信息槽,不压车速

各层surface按VSync提交,fence同步

车速/歌名/导航走统一状态服务

行车模式降媒体帧率、关歌词动画

ADAS/倒车触发Overlay强置顶

车机多窗口的本质是“安全信息永远在最底层且不被覆盖,娱乐信息永远在附加层且只刷脏区”。Z-order不是UI美观问题,是功能安全边界;硬件图层合成省GPU也省延迟;状态同源解决多屏不一致。写应用层时别去管像素混合,只管“我在哪一层、占哪块脏区、优先级多少”——剩下交给合成器。真在仪表上把车速数字被音乐卡片盖掉,不是体验问题,是HMI架构事故。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭