libdrm全解析三十七 —— 源码全解析(34)

接前一篇文章:libdrm全解析三十六 —— 源码全解析(33)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

本文开始对于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函数就讲解完了。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132583505