IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> libdrm的测试程序modetest的覆盖所有plane的测试 -> 正文阅读

[移动开发]libdrm的测试程序modetest的覆盖所有plane的测试

这个测试是在libdrm-2.4.92版本上修改的,为了测试drm。
这个测试程序,找到第一个有效的crtc id之后,就覆盖对应所有的plane合成。
添加了alpha参数和blend的mode的参数,rotation目前我的平台不支持所以没有添加到properties的设置中去
之前这段code是运行在Android平台的,修改了下,又拿到yocto的平台测试。有些diff,是从Android版本上带过来的,
主要的code修改在main函数中。
这个程序比较简单,所以只贴了patch

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 62957d8..92e4edc 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -67,6 +67,8 @@
 #include "buffers.h"
 #include "cursor.h"
 
+static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE;
+
 struct crtc {
 	drmModeCrtc *crtc;
 	drmModeObjectProperties *props;
@@ -119,6 +121,9 @@ struct device {
 		struct bo *bo;
 		struct bo *cursor_bo;
 	} mode;
+
+	int use_atomic;
+	drmModeAtomicReq *req;
 };
 
 static inline int64_t U642I64(uint64_t val)
@@ -781,7 +786,7 @@ static drmModeEncoder *get_encoder_by_id(struct device *dev, uint32_t id)
  * can bind it with a free crtc.
  */
 struct pipe_arg {
-	const char **cons;
+	char **cons;
 	uint32_t *con_ids;
 	unsigned int num_cons;
 	uint32_t crtc_id;
@@ -798,16 +803,21 @@ struct pipe_arg {
 };
 
 struct plane_arg {
-	uint32_t plane_id;  /* the id of plane to use */
+	uint32_t plane_id; /* the id of plane to use */
 	uint32_t crtc_id;  /* the id of CRTC to bind to */
 	bool has_position;
 	int32_t x, y;
 	uint32_t w, h;
 	double scale;
 	unsigned int fb_id;
+	unsigned int old_fb_id;
 	struct bo *bo;
+	struct bo *old_bo;
 	char format_str[5]; /* need to leave room for terminating \0 */
 	unsigned int fourcc;
+	int32_t alpha;
+	int32_t rotation;
+	int32_t blend_mode;
 };
 
 static drmModeModeInfo *
@@ -941,9 +951,10 @@ struct property_arg {
 	char name[DRM_PROP_NAME_LEN+1];
 	uint32_t prop_id;
 	uint64_t value;
+	bool optional;
 };
 
-static void set_property(struct device *dev, struct property_arg *p)
+static bool set_property(struct device *dev, struct property_arg *p)
 {
 	drmModeObjectProperties *props = NULL;
 	drmModePropertyRes **props_info = NULL;
@@ -975,13 +986,13 @@ static void set_property(struct device *dev, struct property_arg *p)
 	if (p->obj_type == 0) {
 		fprintf(stderr, "Object %i not found, can't set property\n",
 			p->obj_id);
-			return;
+		return false;
 	}
 
 	if (!props) {
 		fprintf(stderr, "%s %i has no properties\n",
 			obj_type, p->obj_id);
-		return;
+		return false;
 	}
 
 	for (i = 0; i < (int)props->count_props; ++i) {
@@ -992,18 +1003,25 @@ static void set_property(struct device *dev, struct property_arg *p)
 	}
 
 	if (i == (int)props->count_props) {
-		fprintf(stderr, "%s %i has no %s property\n",
-			obj_type, p->obj_id, p->name);
-		return;
+		if (!p->optional)
+			fprintf(stderr, "%s %i has no %s property\n",
+				obj_type, p->obj_id, p->name);
+		return false;
 	}
 
 	p->prop_id = props->props[i];
 
-	ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
-				       p->prop_id, p->value);
+	if (!dev->use_atomic)
+		ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
+									   p->prop_id, p->value);
+	else
+		ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value);
+
 	if (ret < 0)
 		fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
 			obj_type, p->obj_id, p->name, p->value, strerror(errno));
+
+	return true;
 }
 
 /* -------------------------------------------------------------------------- */
@@ -1049,6 +1067,184 @@ static bool format_support(const drmModePlanePtr ovr, uint32_t fmt)
 	return false;
 }
 
+static void add_property(struct device *dev, uint32_t obj_id,
+			       const char *name, uint64_t value)
+{
+	struct property_arg p;
+
+	p.obj_id = obj_id;
+	strcpy(p.name, name);
+	p.value = value;
+
+	set_property(dev, &p);
+}
+
+static bool add_property_optional(struct device *dev, uint32_t obj_id,
+				  const char *name, uint64_t value)
+{
+	struct property_arg p;
+
+	p.obj_id = obj_id;
+	strcpy(p.name, name);
+	p.value = value;
+	p.optional = true;
+
+	return set_property(dev, &p);
+}
+
+static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
+{
+	unsigned blob_id = 0;
+	/* TODO: support 1024-sized LUTs, when the use-case arises */
+	struct drm_color_lut gamma_lut[256];
+	int i, ret;
+
+	if (fourcc == DRM_FORMAT_C8) {
+		/* TODO: Add C8 support for more patterns */
+		//util_smpte_c8_gamma(256, gamma_lut);
+		drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id);
+	} else {
+		for (i = 0; i < 256; i++) {
+			gamma_lut[i].red =
+			gamma_lut[i].green =
+			gamma_lut[i].blue = i << 8;
+		}
+	}
+
+	add_property_optional(dev, crtc_id, "DEGAMMA_LUT", 0);
+	add_property_optional(dev, crtc_id, "CTM", 0);
+	if (!add_property_optional(dev, crtc_id, "GAMMA_LUT", blob_id)) {
+		uint16_t r[256], g[256], b[256];
+
+		for (i = 0; i < 256; i++) {
+			r[i] = gamma_lut[i].red;
+			g[i] = gamma_lut[i].green;
+			b[i] = gamma_lut[i].blue;
+		}
+
+		ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b);
+		//if (ret)
+		//	fprintf(stderr, "failed to set gamma: %s\n", strerror(errno));
+	}
+}
+
+static int32_t convert_to_drm(int32_t rot) {
+	int32_t rotation = DRM_MODE_ROTATE_0;
+	switch (rot) {
+		case 0:
+			rotation = DRM_MODE_ROTATE_0;
+			break;
+		case 1:
+			rotation = DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_0;
+			break;
+		case 2:
+			rotation = DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_0;
+			break;
+		case 3:
+			rotation = DRM_MODE_ROTATE_180;
+			break;
+		case 4:
+			rotation = DRM_MODE_ROTATE_270;
+			break;
+		case 5:
+			rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
+			break;
+		case 6:
+			rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_Y;
+			break;
+		case 7:
+			rotation = DRM_MODE_ROTATE_90;
+			break;
+		default:
+			rotation = DRM_MODE_ROTATE_0;
+			break;
+	}
+	return rotation;
+}
+
+static int atomic_set_plane(struct device *dev, struct plane_arg *p,
+							int pattern, bool update)
+{
+	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+	struct bo *plane_bo;
+	int crtc_x, crtc_y, crtc_w, crtc_h;
+	struct crtc *crtc = NULL;
+	unsigned int i;
+	unsigned int old_fb_id;
+	int32_t  rotation;
+
+	/* Find an unused plane which can be connected to our CRTC. Find the
+	 * CRTC index first, then iterate over available planes.
+	 */
+	for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) {
+		if (p->crtc_id == dev->resources->res->crtcs[i]) {
+			crtc = &dev->resources->crtcs[i];
+			break;
+		}
+	}
+
+	if (!crtc) {
+		fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
+		return -1;
+	}
+
+	if (!update) {
+		fprintf(stderr, "testing w:h = %4d:%4d, x:y = %4dx%4d, @%s on plane %u, crtc %u , display:w:%d, h:%d, scale = %llf, alpha = %d\n\n",
+			p->w, p->h, p->x, p->y, p->format_str, p->plane_id, p->crtc_id, crtc->mode->hdisplay, crtc->mode->vdisplay, p->scale, p->alpha);
+	}
+
+	rotation = convert_to_drm(p->rotation);
+
+	plane_bo = p->old_bo;
+	p->old_bo = p->bo;
+
+	if (!plane_bo) {
+		plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h,
+				    handles, pitches, offsets, pattern);
+
+		if (plane_bo == NULL)
+			return -1;
+
+		if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc,
+			handles, pitches, offsets, &p->fb_id, 0)) {
+			fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+			return -1;
+		}
+	}
+
+	p->bo = plane_bo;
+
+	old_fb_id = p->fb_id;
+	p->old_fb_id = old_fb_id;
+
+	crtc_w = p->w * p->scale;
+	crtc_h = p->h * p->scale;
+	if (!p->has_position) {
+		/* Default to the middle of the screen */
+		crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+		crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
+	} else {
+		crtc_x = p->x;
+		crtc_y = p->y;
+	}
+
+	add_property(dev, p->plane_id, "FB_ID", p->fb_id);
+	add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id);
+	add_property(dev, p->plane_id, "SRC_X", 0);
+	add_property(dev, p->plane_id, "SRC_Y", 0);
+	add_property(dev, p->plane_id, "SRC_W", p->w << 16);
+	add_property(dev, p->plane_id, "SRC_H", p->h << 16);
+	add_property(dev, p->plane_id, "CRTC_X", crtc_x);
+	add_property(dev, p->plane_id, "CRTC_Y", crtc_y);
+	add_property(dev, p->plane_id, "CRTC_W", crtc_w);
+	add_property(dev, p->plane_id, "CRTC_H", crtc_h);
+	add_property(dev, p->plane_id, "alpha", p->alpha);
+	//add_property(dev, p->plane_id, "rotation", rotation);
+	add_property(dev, p->plane_id, "pixel blend mode", p->blend_mode);
+
+	return 0;
+}
+
 static int set_plane(struct device *dev, struct plane_arg *p)
 {
 	drmModePlane *ovr;
@@ -1060,6 +1256,7 @@ static int set_plane(struct device *dev, struct plane_arg *p)
 	struct crtc *crtc = NULL;
 	unsigned int pipe;
 	unsigned int i;
+	int32_t  rotation;
 
 	/* Find an unused plane which can be connected to our CRTC. Find the
 	 * CRTC index first, then iterate over available planes.
@@ -1107,9 +1304,12 @@ static int set_plane(struct device *dev, struct plane_arg *p)
 		p->w, p->h, p->format_str, plane_id);
 
 	plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h, handles,
-			     pitches, offsets, UTIL_PATTERN_TILES);
-	if (plane_bo == NULL)
+			     pitches, offsets, primary_fill);
+	if (plane_bo == NULL) {
+		fprintf(stderr, "testing %dx%d@%s overlay plane %u\n",
+			p->w, p->h, p->format_str, plane_id);
 		return -1;
+	}
 
 	p->bo = plane_bo;
 
@@ -1119,6 +1319,9 @@ static int set_plane(struct device *dev, struct plane_arg *p)
 		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
 		return -1;
 	}
+	fprintf(stderr, "testing %dx%d@%s overlay plane %u, scale %llf, h %d, v%d, fb = %d, p->fb_id = %d\n",
+		p->w, p->h, p->format_str, plane_id, p->scale, crtc->mode->hdisplay,
+        crtc->mode->vdisplay, dev->fd, p->fb_id);
 
 	crtc_w = p->w * p->scale;
 	crtc_h = p->h * p->scale;
@@ -1130,6 +1333,10 @@ static int set_plane(struct device *dev, struct plane_arg *p)
 		crtc_x = p->x;
 		crtc_y = p->y;
 	}
+	//rotation = convert_to_drm(p->rotation);
+	add_property(dev, plane_id, "alpha", p->alpha);
+	//add_property(dev, plane_id, "rotation", rotation);
+	add_property(dev, plane_id, "pixel blend mode", p->blend_mode);
 
 	/* note src coords (last 4 args) are in Q16 format */
 	if (drmModeSetPlane(dev->fd, plane_id, crtc->crtc->crtc_id, p->fb_id,
@@ -1145,6 +1352,69 @@ static int set_plane(struct device *dev, struct plane_arg *p)
 	return 0;
 }
 
+static void atomic_set_planes(struct device *dev, struct plane_arg *p,
+			      unsigned int count, bool update)
+{
+	unsigned int i, pattern = primary_fill;
+
+	/* set up planes */
+	for (i = 0; i < count; i++) {
+		//if (i > 0)
+			pattern = primary_fill;
+		//else
+			//set_gamma(dev, p[i].crtc_id, p[i].fourcc);
+
+		if (atomic_set_plane(dev, &p[i], pattern, update))
+			return;
+	}
+}
+
+static void atomic_clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		add_property(dev, p[i].plane_id, "FB_ID", 0);
+		add_property(dev, p[i].plane_id, "CRTC_ID", 0);
+		add_property(dev, p[i].plane_id, "SRC_X", 0);
+		add_property(dev, p[i].plane_id, "SRC_Y", 0);
+		add_property(dev, p[i].plane_id, "SRC_W", 0);
+		add_property(dev, p[i].plane_id, "SRC_H", 0);
+		add_property(dev, p[i].plane_id, "CRTC_X", 0);
+		add_property(dev, p[i].plane_id, "CRTC_Y", 0);
+		add_property(dev, p[i].plane_id, "CRTC_W", 0);
+		add_property(dev, p[i].plane_id, "CRTC_H", 0);
+		add_property(dev, p[i].plane_id, "alpha", 255);
+		//add_property(dev, p[i].plane_id, "rotation", 0);
+		add_property(dev, p[i].plane_id, "pixel blend mode", 0);
+	}
+}
+
+static void atomic_clear_FB(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		if (p[i].fb_id) {
+			drmModeRmFB(dev->fd, p[i].fb_id);
+			p[i].fb_id = 0;
+		}
+		if (p[i].old_fb_id) {
+			drmModeRmFB(dev->fd, p[i].old_fb_id);
+			p[i].old_fb_id = 0;
+		}
+		if (p[i].bo) {
+			bo_destroy(p[i].bo);
+			p[i].bo = NULL;
+		}
+		if (p[i].old_bo) {
+			bo_destroy(p[i].old_bo);
+			p[i].old_bo = NULL;
+		}
+
+	}
+}
+
 static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
 {
 	unsigned int i;
@@ -1157,6 +1427,178 @@ static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int c
 	}
 }
 
+static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
+{
+	drmModeConnector *connector;
+	unsigned int i;
+	uint32_t id;
+	char *endp;
+
+	for (i = 0; i < pipe->num_cons; i++) {
+		id = strtoul(pipe->cons[i], &endp, 10);
+		if (endp == pipe->cons[i]) {
+			connector = get_connector_by_name(dev, pipe->cons[i]);
+			if (!connector) {
+				fprintf(stderr, "no connector named '%s'\n",
+					pipe->cons[i]);
+				return -ENODEV;
+			}
+
+			id = connector->connector_id;
+		}
+
+		pipe->con_ids[i] = id;
+	}
+
+	return 0;
+}
+
+static int get_valid_pipes(struct device *dev, struct pipe_arg *pipes) {
+	drmModeEncoder *encoder = NULL;
+	int i = 0;
+	int j = 0;
+	int k = 0;
+
+	struct pipe_arg *pipe = &pipes[0];
+	for (i = 0; i < dev->resources->res->count_encoders; i++) {
+		encoder = dev->resources->encoders[i].encoder;
+		if (!encoder)
+			continue;
+
+		printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+			   encoder->encoder_id,
+			   encoder->crtc_id,
+			   util_lookup_encoder_type_name(encoder->encoder_type),
+			   encoder->possible_crtcs,
+			   encoder->possible_clones);
+		for (j = 0; j < dev->resources->res->count_connectors; j++) {
+			struct connector *_connector = &dev->resources->connectors[i];
+			drmModeConnector *connector = _connector->connector;
+			if (!connector)
+				continue;
+
+			printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t\n",
+			   connector->connector_id,
+			   connector->encoder_id,
+			   util_lookup_connector_status_name(connector->connection),
+			   _connector->name,
+			   connector->mmWidth, connector->mmHeight,
+			   connector->count_modes);
+			for (k = 0; k < connector->count_encoders; k++) {
+				if (encoder->encoder_id == connector->encoders[k]) {
+					pipe->num_cons = 1;
+					pipe->vrefresh = 0;
+					pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
+					pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
+					if (pipe->con_ids == NULL || pipe->cons == NULL) {
+						printf("Fail to alloc pipe->cons or pipe->con_ids\n");
+						return -1;
+					}
+					char temp[10];
+					memset(temp, '\0', 10);
+					sprintf(temp, "%d", connector->connector_id);
+					pipe->cons[0] = strndup(temp, strlen(temp) + 1);
+					fprintf(stderr, "Success to find the first vaild connector id = %s, cons = %s\n",temp, pipe->cons[0]);
+					pipe->crtc_id = encoder->crtc_id;
+					strcpy(pipe->format_str, "XR24");
+					if (pipe_resolve_connectors(dev, pipe) < 0)
+						return -1;
+
+					if (connector->count_modes) {
+						drmModeModeInfo *mode = &connector->modes[0];
+						strncpy(pipe->mode_str, mode->name, strlen(mode->name));
+						fprintf(stderr, "mode name = %s\n", pipe->mode_str);
+					} else {
+						fprintf(stderr, "mode count is 0 !!! \n");
+						return -1;
+					}
+					break;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int get_max_count_for_format(struct device *dev) {
+	int max = 0;
+	int i = 0;
+
+	if (!dev->resources->plane_res)
+		return max;
+
+	for (i = 0; i < dev->resources->plane_res->count_planes; i++) {
+		struct plane *plane = &dev->resources->planes[i];
+		drmModePlane *ovr = plane->plane;
+		if (!ovr)
+			continue;
+
+		printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n",
+			   ovr->plane_id, ovr->crtc_id, ovr->fb_id,
+			   ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
+			   ovr->gamma_size, ovr->possible_crtcs);
+
+		if (!ovr->count_formats)
+			continue;
+		if (max < ovr->count_formats)
+			max = ovr->count_formats;
+	}
+	return max;
+}
+
+static void atomic_set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+	unsigned int i;
+	unsigned int j;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+
+		ret = pipe_find_crtc_and_mode(dev, pipe);
+		if (ret < 0)
+			continue;
+	}
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+		uint32_t blob_id;
+
+		if (pipe->mode == NULL)
+			continue;
+
+		printf("setting mode %s-%dHz on connectors ",
+		       pipe->mode_str, pipe->mode->vrefresh);
+		for (j = 0; j < pipe->num_cons; ++j) {
+			printf("%s, ", pipe->cons[j]);
+			add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc->crtc->crtc_id);
+		}
+		printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
+
+		drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", blob_id);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 1);
+	}
+}
+
+static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+	unsigned int i;
+	unsigned int j;
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+
+		if (pipe->mode == NULL)
+			continue;
+
+		for (j = 0; j < pipe->num_cons; ++j)
+			add_property(dev, pipe->con_ids[j], "CRTC_ID",0);
+
+		add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", 0);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 0);
+	}
+}
 
 static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
 {
@@ -1185,7 +1627,7 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
 
 	bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width,
 		       dev->mode.height, handles, pitches, offsets,
-		       UTIL_PATTERN_SMPTE);
+		       primary_fill);
 	if (bo == NULL)
 		return;
 
@@ -1227,6 +1669,8 @@ static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int co
 			fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
 			return;
 		}
+
+		set_gamma(dev, pipe->crtc->crtc->crtc_id, pipe->fourcc);
 	}
 }
 
@@ -1499,13 +1943,32 @@ static int parse_plane(struct plane_arg *plane, const char *p)
 	} else {
 		plane->scale = 1.0;
 	}
-
-	if (*end == '@') {
+	if (*end == 'R') {
 		p = end + 1;
-		if (strlen(p) != 4)
-			return -EINVAL;
+		plane->rotation = strtol(p, &end, 10);
+	} else {
+		plane->rotation = 0;
+	}
+		fprintf(stderr, "rotation %d\n", plane->rotation);
+	if (*end == 'A') {
+		p = end + 1;
+		plane->alpha = strtol(p, &end, 10);
+		fprintf(stderr, "alpha %d\n", plane->alpha);
+	} else {
+		plane->alpha = 255;
+	}
+		fprintf(stderr, "alpha %d\n", plane->alpha);
+	if (*end == 'M') {
+		p = end + 1;
+		plane->blend_mode = strtol(p, &end, 10);
+	} else {
+		plane->blend_mode = 1;
+	}
+		fprintf(stderr, "blend mode %d\n", plane->blend_mode);
 
-		strcpy(plane->format_str, p);
+	if (*end == '@') {
+		strncpy(plane->format_str, end + 1, 4);
+		plane->format_str[4] = '\0';
 	} else {
 		strcpy(plane->format_str, "XR24");
 	}
@@ -1532,7 +1995,7 @@ static int parse_property(struct property_arg *p, const char *arg)
 
 static void usage(char *name)
 {
-	fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+	fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
 
 	fprintf(stderr, "\n Query options:\n\n");
 	fprintf(stderr, "\t-c\tlist connectors\n");
@@ -1546,6 +2009,8 @@ static void usage(char *name)
 	fprintf(stderr, "\t-C\ttest hw cursor\n");
 	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
 	fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
+	fprintf(stderr, "\t-a \tuse atomic API\n");
+	fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n");
 
 	fprintf(stderr, "\n Generic options:\n\n");
 	fprintf(stderr, "\t-d\tdrop master after mode set\n");
@@ -1583,33 +2048,14 @@ static int cursor_supported(void)
 	return 1;
 }
 
-static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
-{
-	drmModeConnector *connector;
-	unsigned int i;
-	uint32_t id;
-	char *endp;
-
-	for (i = 0; i < pipe->num_cons; i++) {
-		id = strtoul(pipe->cons[i], &endp, 10);
-		if (endp == pipe->cons[i]) {
-			connector = get_connector_by_name(dev, pipe->cons[i]);
-			if (!connector) {
-				fprintf(stderr, "no connector named '%s'\n",
-					pipe->cons[i]);
-				return -ENODEV;
-			}
-
-			id = connector->connector_id;
-		}
-
-		pipe->con_ids[i] = id;
-	}
-
-	return 0;
+static void get_fourcc(char* format, uint32_t fourcc) {
+   sprintf(format, "%c", fourcc);
+   sprintf(format + 1, "%c", fourcc >> 8);
+   sprintf(format + 2, "%c", fourcc >> 16);
+   sprintf(format + 3, "%c", fourcc >> 24);
 }
 
-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static char optstr[] = "acdD:efF:M:P:ps:Cvw:A";
 
 int main(int argc, char **argv)
 {
@@ -1620,6 +2066,7 @@ int main(int argc, char **argv)
 	int drop_master = 0;
 	int test_vsync = 0;
 	int test_cursor = 0;
+	int use_atomic = 0;
 	char *device = NULL;
 	char *module = NULL;
 	unsigned int i;
@@ -1630,6 +2077,8 @@ int main(int argc, char **argv)
 	struct property_arg *prop_args = NULL;
 	unsigned int args = 0;
 	int ret;
+	bool abort = false;
+	bool test_all = false;
 
 	memset(&dev, 0, sizeof dev);
 
@@ -1638,6 +2087,9 @@ int main(int argc, char **argv)
 		args++;
 
 		switch (c) {
+		case 'a':
+			use_atomic = 1;
+			break;
 		case 'c':
 			connectors = 1;
 			break;
@@ -1711,25 +2163,37 @@ int main(int argc, char **argv)
 
 			prop_count++;
 			break;
+		case 'A':
+			test_all = true;
+			break;
 		default:
 			usage(argv[0]);
 			break;
 		}
 	}
 
-	if (!args)
+	if (!args || (args == 1 && use_atomic))
 		encoders = connectors = crtcs = planes = framebuffers = 1;
 
 	dev.fd = util_open(device, module);
 	if (dev.fd < 0)
 		return -1;
 
+	ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
+	if (ret && use_atomic) {
+		fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
+		drmClose(dev.fd);
+		return -1;
+	}
+
+	dev.use_atomic = use_atomic;
+
 	if (test_vsync && !page_flipping_supported()) {
 		fprintf(stderr, "page flipping not supported by drm.\n");
 		return -1;
 	}
 
-	if (test_vsync && !count) {
+	if (!test_all && test_vsync && !count) {
 		fprintf(stderr, "page flipping requires at least one -s option.\n");
 		return -1;
 	}
@@ -1741,15 +2205,18 @@ int main(int argc, char **argv)
 
 	dev.resources = get_resources(&dev);
 	if (!dev.resources) {
+		fprintf(stderr, "failed to find the resources\n");
 		drmClose(dev.fd);
 		return 1;
 	}
 
-	for (i = 0; i < count; i++) {
-		if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
-			free_resources(dev.resources);
-			drmClose(dev.fd);
-			return 1;
+	if (!test_all) {
+		for (i = 0; i < count; i++) {
+			if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
+				free_resources(dev.resources);
+				drmClose(dev.fd);
+				return 1;
+			}
 		}
 	}
 
@@ -1764,40 +2231,247 @@ int main(int argc, char **argv)
 	for (i = 0; i < prop_count; ++i)
 		set_property(&dev, &prop_args[i]);
 
-	if (count || plane_count) {
-		uint64_t cap = 0;
+	if (dev.use_atomic) {
+		dev.req = drmModeAtomicAlloc();
+
+		if (count && plane_count && !test_all) {
+			uint64_t cap = 0;
+			int connect_id = 0;
+
+			ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+			if (ret || cap == 0) {
+				fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+				return 1;
+			}
+
+			atomic_set_mode(&dev, pipe_args, count);
+			atomic_set_planes(&dev, plane_args, plane_count, false);
+
+			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			if (ret) {
+				fprintf(stderr, "Atomic Commit failed [1]\n");
+				return 1;
+			}
+
+			gettimeofday(&pipe_args->start, NULL);
+			pipe_args->swap_count = 0;
+
+			while (test_vsync) {
+				drmModeAtomicFree(dev.req);
+				dev.req = drmModeAtomicAlloc();
+				atomic_set_planes(&dev, plane_args, plane_count, true);
+
+				ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+				if (ret) {
+					fprintf(stderr, "Atomic Commit failed [2]\n");
+					return 1;
+				}
+
+				pipe_args->swap_count++;
+				if (pipe_args->swap_count == 60) {
+					struct timeval end;
+					double t;
+
+					gettimeofday(&end, NULL);
+					t = end.tv_sec + end.tv_usec * 1e-6 -
+				    (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6);
+					fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t);
+					pipe_args->swap_count = 0;
+					pipe_args->start = end;
+				}
+			}
+			drmModeAtomicFree(dev.req);
+			dev.req = drmModeAtomicAlloc();
+			if (drop_master)
+				drmDropMaster(dev.fd);
+
+			getchar();
+
+			atomic_clear_mode(&dev, pipe_args, count);
+			atomic_clear_planes(&dev, plane_args, plane_count);
+			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			if (ret) {
+				fprintf(stderr, "Atomic Commit failed\n");
+				return 1;
+			}
+
+			atomic_clear_FB(&dev, plane_args, plane_count);
+
+			drmModeAtomicFree(dev.req);
+		} else {
+			struct pipe_arg *pipes = NULL;
+			struct plane_arg *planes = NULL;
+			uint32_t i = 0;
+			uint32_t j = 0;
+			int max_format_count = 0;
+			char format[5];
+			uint64_t cap = 0;
+			int connect_id = 0;
+			int valid_plane_count = 0;
+			int vdisplay = 0;
+			int hdisplay = 0;
+			int valid_planes = 0;
+			struct pipe_arg *pipe = NULL;
+			fprintf(stderr, "\n\n");
+			fprintf(stderr, "For checking the plane color, you'd best to know info about color:\n");
+			fprintf(stderr, "|       postion      |       color               |     format                                                                                |\n");
+			fprintf(stderr, "| top middle bottom  | red/grey/ini-phase        | XR4H XB4H AR4H AB4H                                                                       |\n");
+			fprintf(stderr, "| top middle bottom  | magenta/black/super white | AR24 XR24 AB24 XB24 RA24 RX24 BA24 BX24 AR30 XR30 AB30 XB30 RA30 RX30 BA30 BX30           |\n");
+			fprintf(stderr, "| top middle bottom  | yellow/green/black        | AR12 XR12 AB12 XB12 RA12 RX12 BA12 BX12 AR15 XR15 AB15 XB15 RA15 RX15 BA15 BX15 RG16 BG16 |\n");
+			fprintf(stderr, "| top middle bottom  | cyan/grey/quarature       | BG24 RG24                                                                                 |\n");
+			fprintf(stderr, "| top middle bottom  | green/blue/black          | NV21 NV21 NV16 NV61 YU12 YV12                                                             |\n");
+			fprintf(stderr, "| top middle bottom  | red/blue/green            | UYVY VYUY YUYV YVYU                                                                       |\n");
+			fprintf(stderr, "\n\n");
+
+			ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+			if (ret || cap == 0) {
+				fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+				return 1;
+			}
 
-		ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
-		if (ret || cap == 0) {
-			fprintf(stderr, "driver doesn't support the dumb buffer API\n");
-			return 1;
+			pipes = realloc(pipes, sizeof(*pipes));
+			if (pipes == NULL) {
+				fprintf(stderr, "memory allocation failed\n");
+				return 1;
+			}
+			memset(&pipes[0], 0, sizeof(*pipes));
+			if (get_valid_pipes(&dev, pipes)) {
+				free_resources(dev.resources);
+				drmClose(dev.fd);
+				return 1;
+			}
+			if (!dev.resources->plane_res) {
+				fprintf(stderr, "plane resource is null \n");
+				return 1;
+			}
+
+			max_format_count = get_max_count_for_format(&dev);
+		    pipe = &pipes[0];
+			for (j = 0; j < dev.resources->plane_res->count_planes; j++) {
+				struct plane *plane = &dev.resources->planes[j];
+				drmModePlane *drm_plane = plane->plane;
+				if (drm_plane->crtc_id == 0) {
+                    drm_plane->crtc_id = pipe->crtc->crtc->crtc_id;
+				}
+				planes = realloc(planes,
+							 (valid_plane_count + 1) * sizeof *planes);
+				if (planes == NULL) {
+					fprintf(stderr, "memory allocation failed\n");
+					return 1;
+				}
+				memset(&planes[valid_plane_count], 0, sizeof(*planes));
+				valid_plane_count++;
+			}
+			for (i = 0; i < max_format_count * 2; i++) {
+				valid_planes = 0;
+				atomic_set_mode(&dev, pipes, 1);
+				vdisplay = pipe->crtc->mode->vdisplay;
+				hdisplay = pipe->crtc->mode->hdisplay;
+                if (hdisplay % 16 != 0)
+                    hdisplay = hdisplay + 16 - hdisplay % 16;//drm driver require 16 Bytes aligned for addr
+
+				/*
+				 * Construct plan_arg to test all the planes which are valid.
+				 * crtc cannot be 0, otherwise driver will return error.
+				 * 1. plan_arg w/h is buffer width/height which are not larger than framebuffer size.
+				 * 2. x/y  is the pointer which is the begin of buffer display.
+				 * 3. to test different formats to compose, choose (i + j * 6) % max_format_count as the index of formats.
+				 */
+				for (j = 0; j < dev.resources->plane_res->count_planes; j++) {
+					struct plane *plane = &dev.resources->planes[j];
+					drmModePlane *drm_plane = plane->plane;
+					if (drm_plane->crtc_id == 0) {
+                        drm_plane->crtc_id = pipe->crtc->crtc->crtc_id;
+					}
+					int index = j;
+					int sub = (valid_plane_count - 1) * 2 * 16; // drm driver require 16 Bytes aligned for addr. so 112 = 16 * 7
+					int iformat = (i + j * 6) % max_format_count;
+					if (iformat >= drm_plane->count_formats) {
+                        iformat = drm_plane->count_formats-1;
+					}
+					get_fourcc(format, drm_plane->formats[iformat]);
+                    if (strcmp(format, "BX24") == 0)
+                        continue;
+					strncpy(planes[valid_planes].format_str, format, 4);
+					planes[valid_planes].fourcc = drm_plane->formats[iformat];
+					planes[valid_planes].plane_id = drm_plane->plane_id;
+					planes[valid_planes].w = index % valid_plane_count * 16 + (hdisplay - sub);
+					planes[valid_planes].h = index % valid_plane_count * 16 + (hdisplay - sub);
+					planes[valid_planes].crtc_id = drm_plane->crtc_id;
+					planes[valid_planes].x = (index % valid_plane_count) * 16;
+					planes[valid_planes].y = (index % valid_plane_count) * 16;
+					planes[valid_planes].scale = ((i + j + 4) % 10) * 0.1 + 0.1;
+					planes[valid_planes].rotation = (i + j) % 8;//format count may be more than roatation types
+					planes[valid_planes].blend_mode = (i + j) % 3;
+					planes[valid_planes].alpha = ((j + i) * 100 + 80) % 255;
+					planes[valid_planes].has_position = true;
+					planes[valid_planes].bo = NULL;
+					planes[valid_planes].old_bo = NULL;
+
+					fprintf(stderr, " planesetting 2 [valid_planes = %d\n", valid_planes);
+					valid_planes++;
+				}
+				atomic_set_planes(&dev, planes, valid_planes, false);
+
+				ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+				if (ret) {
+					fprintf(stderr, "Atomic Commit failed [1] ret = %d \n", ret);
+					return 1;
+				}
+				sleep(8);
+				/*
+				 * To show different size of buffer, we have to release the old buffer.
+				 * Because the drm driver will return error for drmModeAtomicCommit.
+				 */
+				atomic_clear_FB(&dev, planes, valid_planes);
+				drmModeAtomicFree(dev.req);
+				dev.req = drmModeAtomicAlloc();
+			}
+
+			atomic_clear_mode(&dev, pipes, count);
+			atomic_clear_planes(&dev, planes, valid_planes);
+			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			if (ret) {
+				fprintf(stderr, "Atomic Commit failed\n");
+				return 1;
+			}
 		}
+	} else {
+		if (count || plane_count) {
+			uint64_t cap = 0;
 
-		if (count)
-			set_mode(&dev, pipe_args, count);
+			ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+			if (ret || cap == 0) {
+				fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+				return 1;
+			}
 
-		if (plane_count)
-			set_planes(&dev, plane_args, plane_count);
+			if (count)
+				set_mode(&dev, pipe_args, count);
 
-		if (test_cursor)
-			set_cursors(&dev, pipe_args, count);
+			if (plane_count)
+				set_planes(&dev, plane_args, plane_count);
 
-		if (test_vsync)
-			test_page_flip(&dev, pipe_args, count);
+			if (test_cursor)
+				set_cursors(&dev, pipe_args, count);
 
-		if (drop_master)
-			drmDropMaster(dev.fd);
+			if (test_vsync)
+				test_page_flip(&dev, pipe_args, count);
 
-		getchar();
+			if (drop_master)
+				drmDropMaster(dev.fd);
 
-		if (test_cursor)
-			clear_cursors(&dev);
+			getchar();
 
-		if (plane_count)
-			clear_planes(&dev, plane_args, plane_count);
+			if (test_cursor)
+				clear_cursors(&dev);
 
-		if (count)
-			clear_mode(&dev);
+			if (plane_count)
+				clear_planes(&dev, plane_args, plane_count);
+
+			if (count)
+				clear_mode(&dev);
+		}
 	}
 
 	free_resources(dev.resources);
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:31:59  更:2021-08-11 12:32:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 8:38:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码