vblank_handler怎么用
时间: 2023-07-06 19:36:00 浏览: 290
vblank_handler 函数用于处理显示垂直同步信号 (VBlank) 的中断处理程序,在 Linux 内核中使用 DRM 子系统时比较常见。下面是一个 vblank_handler 函数的使用示例:
```c
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
static volatile bool vblank_occurred = false;
static void vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
{
vblank_occurred = true;
}
int main(int argc, char *argv[])
{
int fd = open("/dev/dri/card0", O_RDWR);
drmEventContext evctx = {
.version = DRM_EVENT_CONTEXT_VERSION,
.vblank_handler = vblank_handler,
};
drmModeRes *resources = drmModeGetResources(fd);
drmModeConnector *connector = drmModeGetConnector(fd, resources->connectors[0]);
drmModeCrtc *crtc = drmModeGetCrtc(fd, connector->crtc_id);
drmModeModeInfo mode = connector->modes[0];
uint32_t fb_id, handle;
drmModeCreateDumb create_arg = {
.width = mode.hdisplay,
.height = mode.vdisplay,
.bpp = 32,
};
drmModeAddFB add_arg = {
.width = mode.hdisplay,
.height = mode.vdisplay,
.pitch = create_arg.width * 4,
.depth = 24,
.bpp = 32,
};
drmModeAtomicReq *req;
int ret;
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
if (ret < 0) {
fprintf(stderr, "Failed to create dumb buffer: %s\n", strerror(errno));
return 1;
}
fb_id = add_arg.fb_id = create_arg.handle;
ret = drmModeAddFB(fd, add_arg.width, add_arg.height, add_arg.depth, add_arg.bpp, add_arg.pitch, create_arg.handle, &fb_id);
if (ret < 0) {
fprintf(stderr, "Failed to add framebuffer: %s\n", strerror(errno));
goto err_fb;
}
ret = drmModeSetCrtc(fd, crtc->crtc_id, fb_id, 0, 0, &connector->connector_id, 1, &mode);
if (ret < 0) {
fprintf(stderr, "Failed to set CRTC: %s\n", strerror(errno));
goto err_fb;
}
req = drmModeAtomicAlloc();
drmModeAtomicAddProperty(req, crtc->crtc_id, DRM_MODE_OBJECT_CRTC, DRM_MODE_PROP_ACTIVE, 1);
drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
while (true) {
while (!vblank_occurred)
drmHandleEvent(fd, &evctx);
vblank_occurred = false;
/* Draw to buffer here */
drmModePageFlip(fd, crtc->crtc_id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, &vblank_occurred);
}
drmModeAtomicFree(req);
drmModeFreeCrtc(crtc);
drmModeFreeConnector(connector);
drmModeFreeResources(resources);
drmModeRmFB(fd, fb_id);
drmModeRmDumb(fd, &create_arg);
close(fd);
return 0;
err_fb:
drmModeRmFB(fd, fb_id);
drmModeRmDumb(fd, &create_arg);
close(fd);
return 1;
}
```
在上述示例中,我们首先打开 /dev/dri/card0 设备文件,然后通过 drmModeGetResources 和 drmModeGetConnector 函数获取显示器的资源信息和连接器信息。接着,我们创建一个基于 VBlank 中断的事件处理程序 vblank_handler,并将其与 drmEventContext 结构体关联起来。在主循环中,我们使用 drmHandleEvent 函数监听事件,当 VBlank 中断发生时,vblank_handler 函数将会被调用。在 vblank_handler 函数中,设置 vblank_occurred 标志并退出函数。在主循环中,我们可以检查 vblank_occurred 标志是否为真,如果为真,则执行一些绘制操作,并使用 drmModePageFlip 函数请求显示器进行页面翻转。通过这种方式,我们可以使用 vblank_handler 函数来实现基于 VBlank 中断的显示管理。
阅读全文