接前一篇文章:libdrm全解析三十六 —— 源码全解析(33)
本文参考以下博文:
特此致谢!
本文开始对于DRM_IOCTL_MODE_SETCRTC对应的Userspace API drmModeSetCrtc()进行解析。再次贴出该函数源码,在xf86drmMode.c中,如下:
drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
drmModeModeInfoPtr mode)
{
struct drm_mode_crtc crtc;
memclear(crtc);
crtc.x = x;
crtc.y = y;
crtc.crtc_id = crtcId;
crtc.fb_id = bufferId;
crtc.set_connectors_ptr = VOID2U64(connectors);
crtc.count_connectors = count;
if (mode) {
memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
crtc.mode_valid = 1;
}
return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}
核心结构struct drm_mode_crtc的定义在include/libdrm/drm_mode.h中,如下:
struct drm_mode_crtc {
__u64 set_connectors_ptr;
__u32 count_connectors;
__u32 crtc_id; /**< Id */
__u32 fb_id; /**< Id of framebuffer */
__u32 x; /**< x Position on the framebuffer */
__u32 y; /**< y Position on the framebuffer */
__u32 gamma_size;
__u32 mode_valid;
struct drm_mode_modeinfo mode;
};
实际使用中调用的代码示例片段如下:
drmModeSetCrtc(fd, crtc_id, buf[0].fb_id,
0, 0, &conn_id, 1, &connector->modes[0]); //初始化和设置crtc,对应显存立即刷新
drmModeSetCrtc函数的参数:fd是显卡设备对应的文件描述符;crtcId是调用drmModeGetResources函数时得到的crtc的id;bufferId是调用drmModeAddFB函数时得到的framebuffer的id;x和y分别对应framebuffer中的横纵坐标,connectors此处传入的是调用drmModeGetResources函数时得到的connector的id;count是connector的数量,此处传入1,代表有1个conector;mode是drmModeGetConnector函数得到的connector中的成员,代表显示模式。
drmModeModeInfo结构的定义在xf86drmMode.h中,代码如下:
typedef struct _drmModeModeInfo {
uint32_t clock;
uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;
uint32_t vrefresh;
uint32_t flags;
uint32_t type;
char name[DRM_DISPLAY_MODE_LEN];
} drmModeModeInfo, *drmModeModeInfoPtr;
mode的类型是drmModeModeInfoPtr,而crtc.mode的类型是struct drm_mode_modeinfo,能够通过mode给crtc.mode赋值吗?这里再次贴出struct drm_mode_modeinfo的源码,在include/libdrm/drm_mode.h中,如下:
/**
* struct drm_mode_modeinfo - Display mode information.
* @clock: pixel clock in kHz
* @hdisplay: horizontal display size
* @hsync_start: horizontal sync start
* @hsync_end: horizontal sync end
* @htotal: horizontal total size
* @hskew: horizontal skew
* @vdisplay: vertical display size
* @vsync_start: vertical sync start
* @vsync_end: vertical sync end
* @vtotal: vertical total size
* @vscan: vertical scan
* @vrefresh: approximate vertical refresh rate in Hz
* @flags: bitmask of misc. flags, see DRM_MODE_FLAG_* defines
* @type: bitmask of type flags, see DRM_MODE_TYPE_* defines
* @name: string describing the mode resolution
*
* This is the user-space API display mode information structure. For the
* kernel version see struct drm_display_mode.
*/
struct drm_mode_modeinfo {
__u32 clock;
__u16 hdisplay;
__u16 hsync_start;
__u16 hsync_end;
__u16 htotal;
__u16 hskew;
__u16 vdisplay;
__u16 vsync_start;
__u16 vsync_end;
__u16 vtotal;
__u16 vscan;
__u32 vrefresh;
__u32 flags;
__u32 type;
char name[DRM_DISPLAY_MODE_LEN];
};
可见,drmModeModeInfoPtr结构与struct drm_mode_modeinfo结构中存在着一对一的关系,因此是能够赋值的。
根据以上分析,drmModeSetCrtc函数的作用是利用之前的到的各信息,初始化整个硬件管线(pipeline)并显示图像。
至此,drmModeSetCrtc函数就讲解完了。