编辑
2025-01-20
工作知识
0
请注意,本文编写于 137 天前,最后修改于 137 天前,其中某些信息可能已经过时。

目录

一、drmModeAtomicCommit
二、调用关系
三、Openharmony的使用
四、调试方向

在调试Openharmony的时候,发现开机logo的图层并没有消失,故分析drmModeSet的api,发现了一个关于atomic modestting相关的宏可以workaround解决此问题,但是后面找到根本原因了,故此修改无效,仅作知识了解储备,此文章总结一下这两个宏的区别和联系

一、drmModeAtomicCommit

关于drmModeAtomicCommit的函数,其来源于libdrm库,参考kwin的实现,可以查到具体描述如下:

参考如下

https://github.com/KDE/kwin/blob/master/src/backends/drm/overview.md?plain=1

image.png 可以知道,drmModeAtomicCommit会提交atomic property change给内核drm框架

对于DRM_MODE_ATOMIC_NONBLOCK,代表这次提交的值不会block

对于DRM_MODE_ATOMIC_ALLOW_MODESET,

其会提交所有modeset的改变,与DRM_MODE_ATOMIC_NONBLOCK不同的是,他会阻塞直到内核drm完成modeset的property完成改变

二、调用关系

drmModeAtomicCommit最终会调用到内核的ioctl判断,流程如下:

drmModeAtomicCommit----> DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);----> drm_ioctl---->DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER),--→drm_mode_atomic_ioctl

此时可以观察如下代码:

if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { ret = drm_atomic_nonblocking_commit(state); } else { if (drm_debug_enabled(DRM_UT_STATE)) drm_atomic_print_state(state); ret = drm_atomic_commit(state); }

这里可以发现,如果设置DRM_MODE_ATOMIC_NONBLOCK和不设置DRM_MODE_ATOMIC_NONBLOCK,代码调用函数不一样,如下:

int drm_atomic_nonblocking_commit(struct drm_atomic_state *state) { struct drm_mode_config *config = &state->dev->mode_config; int ret; ret = drm_atomic_check_only(state); if (ret) return ret; DRM_DEBUG_ATOMIC("committing %p nonblocking\n", state); return config->funcs->atomic_commit(state->dev, state, true); } int drm_atomic_commit(struct drm_atomic_state *state) { struct drm_mode_config *config = &state->dev->mode_config; int ret; ret = drm_atomic_check_only(state); if (ret) return ret; DRM_DEBUG_ATOMIC("committing %p\n", state); return config->funcs->atomic_commit(state->dev, state, false); }

对于回调函数atomic_commit,rockchip平台如下设置

static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { .fb_create = rockchip_fb_create, .output_poll_changed = rockchip_drm_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, };

所以我们重点留意drm_atomic_helper_commit内的判断如下:

if (!nonblock) { ret = drm_atomic_helper_wait_for_fences(dev, state, true); if (ret) goto err; } if (nonblock) queue_work(system_unbound_wq, &state->commit_work); else commit_tail(state);

这里可以发现,如果是不是nonblock commit,则先会drm_atomic_helper_wait_for_fences,这里会调用dma_fence_wait,用于睡眠等待fence(sleep until the fence gets signaled),如果fence信号触发,则直接提交到尾 commit_tail(state) 直接渲染

而如果是nonblock commit,则直接将这个事件通过queue_work发送到wq上,这个wq的函数如下:

static void commit_work(struct work_struct *work) { struct drm_atomic_state *state = container_of(work, struct drm_atomic_state, commit_work); commit_tail(state); }

这里可以看到如果wq工作时,才调用commit_tail提交到尾

三、Openharmony的使用

在Openharmony的代码中可以知道,只有在更新DrmMode的时候才执行阻塞提交DRM_MODE_ATOMIC_ALLOW_MODESET,而对于每一帧Composition的时候,只是DRM_MODE_ATOMIC_NONBLOCK非阻塞提交。鉴于此,我们可以在每一帧Composition执DRM_MODE_ATOMIC_ALLOW_MODESET,但根据上述代码分析,可能带来图形的性能损失,故不可行。

四、调试方向

根据如上,了解到了drm在atomic commit的时候,可以选择block和nonblock,如果我都设置block,则开机logo的问题确实解决了,鉴于分析代码的时候发现,此方法可能带来性能损失,故仍继续寻找根因。

出现开机后开机logo的图层没消失的主要原因是应该是openharmony图层设置存在问题,故应该从Plane查起。