modetest工具测试(linux-5.10)

这篇具有很好参考价值的文章主要介绍了modetest工具测试(linux-5.10)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(102条消息) modetest编译、原理分析_空腹吃饭的博客-CSDN博客

(102条消息) tools:drm-kms调试手段[modetest]_drm_debug_kms_maze.ma的博客-CSDN博客

本内容通过modetest的打印,了解drm中各个object之间的关联,即如何正确的设置crtc,connector,encoder,plane的组合,才能正确的显示成功。内核驱动在加载后需要创建crtc,connector,encoder,plane等。且他们直接需要正确的匹配,比如connector和encoder。

在设置显示之前(内核模块加载完毕):

输出当前内核中的connectors: 

modes是和当前connector关联的modes个数。encoders是encoder的列表。如果有多个会按逗号分隔。当前只有是37号。当前encoder是0说明还没有设置。

root@wzm-virtual-machine:/home/wzm# modetest   -c 
Connectors:
id      encoder status          name            size (mm)       modes   encoders
36      0       connected       Virtual-1       0x0             25      37
  modes:
        name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  800x600 60 800 850 900 950 600 650 700 750 42750 flags: nhsync, pvsync; type: preferred, driver
  3840x2400 60 3840 3888 3920 4000 2400 2403 2409 2469 592250 flags: phsync, nvsync; type: driver
  3840x2160 60 3840 3888 3920 4000 2160 2163 2168 2222 533000 flags: phsync, nvsync; type: driver
  2880x1800 60 2880 2928 2960 3040 1800 1803 1809 1852 337500 flags: phsync, nvsync; type: driver
  2560x1600 60 2560 2752 3032 3504 1600 1603 1609 1658 348500 flags: nhsync, pvsync; type: driver
  2560x1440 60 2560 2608 2640 2720 1440 1443 1448 1481 241500 flags: phsync, nvsync; type: driver
  1920x1440 60 1920 2048 2256 2600 1440 1441 1444 1500 234000 flags: nhsync, pvsync; type: driver
  1856x1392 60 1856 1952 2176 2528 1392 1393 1396 1439 218250 flags: nhsync, pvsync; type: driver
  1792x1344 60 1792 1920 2120 2448 1344 1345 1348 1394 204750 flags: nhsync, pvsync; type: driver
  1920x1200 60 1920 2056 2256 2592 1200 1203 1209 1245 193250 flags: nhsync, pvsync; type: driver
  1920x1080 60 1920 2048 2248 2576 1080 1083 1088 1120 173000 flags: nhsync, pvsync; type: driver
  1600x1200 60 1600 1664 1856 2160 1200 1201 1204 1250 162000 flags: phsync, pvsync; type: driver
  1680x1050 60 1680 1784 1960 2240 1050 1053 1059 1089 146250 flags: nhsync, pvsync; type: driver
  1400x1050 60 1400 1488 1632 1864 1050 1053 1057 1089 121750 flags: nhsync, pvsync; type: driver
  1280x1024 60 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, pvsync; type: driver
  1440x900 60 1440 1520 1672 1904 900 903 909 934 106500 flags: nhsync, pvsync; type: driver
  1280x960 60 1280 1376 1488 1800 960 961 964 1000 108000 flags: phsync, pvsync; type: driver
  1360x768 60 1360 1424 1536 1792 768 771 777 795 85500 flags: phsync, pvsync; type: driver
  1280x800 60 1280 1352 1480 1680 800 803 809 831 83500 flags: phsync, nvsync; type: driver
  1152x864 75 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, pvsync; type: driver
  1280x768 60 1280 1344 1472 1664 768 771 778 798 79500 flags: nhsync, pvsync; type: driver
  1280x720 60 1280 1344 1472 1664 720 723 728 748 74500 flags: nhsync, pvsync; type: driver
  1024x768 60 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, nvsync; type: driver
  800x600 60 800 840 968 1056 600 601 605 628 40000 flags: phsync, pvsync; type: driver
  640x480 60 640 656 752 800 480 489 492 525 25175 flags: nhsync, nvsync; type: driver
  props:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 3
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0
        6 non-desktop:
                flags: immutable range
                values: 0 1
                value: 0
        4 TILE:
                flags: immutable blob
                blobs:

                value:
        20 CRTC_ID:
                flags: object


41      0       disconnected    Virtual-2       0x0             25      42
  modes:
        index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 800x600 60.00 800 850 900 950 600 650 700 750 42750 flags: nhsync, pvsync; type: preferred, driver
.....省略输出

drm_connector结构体: 

struct drm_connector
{
    u32 possible_encoders; //encoders位掩码
    struct drm_encoder *encoder;
}

ast驱动中初始化connetor和encoder的地方:

static int ast_connector_init(struct drm_device *dev)
{
        struct ast_connector *ast_connector;
        struct drm_connector *connector;
        struct drm_encoder *encoder;

        ast_connector = kzalloc(sizeof(struct ast_connector), GFP_KERNEL);
        if (!ast_connector)
                return -ENOMEM;

        connector = &ast_connector->base;
        drm_connector_init(dev, connector, &ast_connector_funcs, DRM_MODE_CONNECTOR_VGA);

        drm_connector_helper_add(connector, &ast_connector_helper_funcs);

        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;

        drm_connector_register(connector);

        connector->polled = DRM_CONNECTOR_POLL_CONNECT;

        encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
        drm_connector_attach_encoder(connector, encoder); //这里建立connector和encoder

        ast_connector->i2c = ast_i2c_create(dev);
        if (!ast_connector->i2c)
                DRM_ERROR("failed to add ddc bus for connector\n");

        return 0;
}

 drm_connector_attach_encoder函数:一般驱动在初始化connecor的时候调用。如果有多个encoder和connector则多次调用。

int drm_connector_attach_encoder(struct drm_connector *connector,
				 struct drm_encoder *encoder)
{
	/*
	 * In the past, drivers have attempted to model the static association
	 * of connector to encoder in simple connector/encoder devices using a
	 * direct assignment of connector->encoder = encoder. This connection
	 * is a logical one and the responsibility of the core, so drivers are
	 * expected not to mess with this.
	 *
	 * Note that the error return should've been enough here, but a large
	 * majority of drivers ignores the return value, so add in a big WARN
	 * to get people's attention.
	 */
	if (WARN_ON(connector->encoder))
		return -EINVAL;

	connector->possible_encoders |= drm_encoder_mask(encoder);

	return 0;
}

位图:drm_encoder.h  //就是第几个左移几位。比如第0个就是0x1
static inline u32 drm_encoder_mask(const struct drm_encoder *encoder)
{
	return 1 << drm_encoder_index(encoder);
}
static inline unsigned int drm_encoder_index(const struct drm_encoder *encoder)
{
	return encoder->index;
}

connector的encoder是什么时候设置的?

1:目前在drm_crtc_helper_set_config函数中看到:

调用路径是drm_mode_setcrtc 后会通过__drm_mode_set_config_internal->drm_crtc_helper_set_config:

int drm_crtc_helper_set_config(struct drm_mode_set *set,
			       struct drm_modeset_acquire_ctx *ctx)
{
......
	/* a) traverse passed in connector list and get encoders for them */
	count = 0;
	drm_connector_list_iter_begin(dev, &conn_iter);
	drm_for_each_connector_iter(connector, &conn_iter) {
		const struct drm_connector_helper_funcs *connector_funcs =
			connector->helper_private;
		new_encoder = connector->encoder;
		for (ro = 0; ro < set->num_connectors; ro++) {
			if (set->connectors[ro] == connector) { //匹配到用户传入的connector
				if (connector_funcs->best_encoder)
					new_encoder = connector_funcs->best_encoder(connector);  //调用best_encoder获取合适的encoder
				else
					new_encoder = drm_connector_get_single_encoder(connector);

				/* if we can't get an encoder for a connector
				   we are setting now - then fail */
				if (new_encoder == NULL)
					/* don't break so fail path works correct */
					fail = 1;

				if (connector->dpms != DRM_MODE_DPMS_ON) {
					DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
					mode_changed = true;
				}

				break;  
			}
		}

		if (new_encoder != connector->encoder) { //找到新的encoder。
			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
			mode_changed = true;
			/* If the encoder is reused for another connector, then
			 * the appropriate crtc will be set later.
			 */
			if (connector->encoder)
				connector->encoder->crtc = NULL;
			connector->encoder = new_encoder;  //设置encoder
		}
	}
	drm_connector_list_iter_end(&conn_iter);
......
}

2:drm_atomic_helper.c. TODO

输出当前内核的encoders:

root@wzm-virtual-machine:/home/wzm/libdrm/build/tests/modetest# ./modetest -e
trying to open device 'i915'...failed
trying to open device 'amdgpu'...failed
trying to open device 'radeon'...failed
trying to open device 'nouveau'...failed
trying to open device 'vmwgfx'...done
Encoders:
id	crtc	type	possible crtcs	possible clones	
37	0	Virtual	0x00000001	0x00000001
42	0	Virtual	0x00000002	0x00000002
47	0	Virtual	0x00000004	0x00000004
52	0	Virtual	0x00000008	0x00000008
57	0	Virtual	0x00000010	0x00000010
62	0	Virtual	0x00000020	0x00000020
67	0	Virtual	0x00000040	0x00000040
72	0	Virtual	0x00000080	0x00000080

 possible_crtcs通常是驱动在是初始化connector同时直接设置的,比如ast驱动:

static int ast_encoder_init(struct drm_device *dev)
{
        struct ast_encoder *ast_encoder;

        ast_encoder = kzalloc(sizeof(struct ast_encoder), GFP_KERNEL);
        if (!ast_encoder)
                return -ENOMEM;

        drm_encoder_init(dev, &ast_encoder->base, &ast_enc_funcs,
                         DRM_MODE_ENCODER_DAC, NULL);
        drm_encoder_helper_add(&ast_encoder->base, &ast_enc_helper_funcs);

        ast_encoder->base.possible_crtcs = 1; //直接设置。。这里就限定了两者的匹配关系。位图意味着就是第0个crtc。(1左移0)
        return 0;
}

encoder中的crtc是什么时候设置的?

 和connector的encoder设置一样,在是drm_mode_setcrtc 后会通过__drm_mode_set_config_internal->drm_crtc_helper_set_config:

int drm_crtc_helper_set_config(struct drm_mode_set *set,
			       struct drm_modeset_acquire_ctx *ctx)
{	
.....
    count = 0;
	drm_connector_list_iter_begin(dev, &conn_iter);
	drm_for_each_connector_iter(connector, &conn_iter) {
		if (!connector->encoder) //需确保有encoder,前面已经设置。
			continue;

		if (connector->encoder->crtc == set->crtc)  //如果encoder的crtc是和新传入的一样,设置NULL
			new_crtc = NULL;
		else
			new_crtc = connector->encoder->crtc;

		for (ro = 0; ro < set->num_connectors; ro++) {
			if (set->connectors[ro] == connector)
				new_crtc = set->crtc;
		}

		/* Make sure the new CRTC will work with the encoder */
		if (new_crtc &&
		    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {  //确保crtc在encoder的位图中
			ret = -EINVAL;
			drm_connector_list_iter_end(&conn_iter);
			goto fail;
		}
		if (new_crtc != connector->encoder->crtc) {  //是全新的crtc。首次肯定是满足条件的。
			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
			mode_changed = true;
			connector->encoder->crtc = new_crtc; //更新encoder中的crtc
		}
		if (new_crtc) {
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n",
				      connector->base.id, connector->name,
				      new_crtc->base.id, new_crtc->name);
		} else {
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
				      connector->base.id, connector->name);
		}
	}
	drm_connector_list_iter_end(&conn_iter);
....
}

输出当前内核的crtc和plane:

root@wzm-virtual-machine:/home/wzm/libdrm/build/tests/modetest# ./modetest -p
CRTCs:
id      fb      pos     size
38      0       (0,0)   (0x0)         //这里的fb是crtc->primary的fb。当前没有设置显示,所以为0
   0 0 0 0 0 0 0 0 0 0 flags: ; type: 
  props:
        22 ACTIVE:
                flags: range
                values: 0 1
                value: 0
        23 MODE_ID:
                flags: blob
                blobs:

                value:
        19 OUT_FENCE_PTR:
                flags: range
                values: 0 18446744073709551615
                value: 0
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0
43      0       (0,0)   (0x0)
   0 0 0 0 0 0 0 0 0 0 flags: ; type: 
  props:
        22 ACTIVE:
                flags: range
                values: 0 1
                value: 0
        23 MODE_ID:
                flags: blob
                blobs:

                value:
        19 OUT_FENCE_PTR:
                flags: range
                values: 0 18446744073709551615
                value: 0
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0

.....

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
34      0       0       0,0             0,0     0               0x00000001 //当前plane可能的crtc,详见函数drm_crtc_init_with_planes赋值。因此通常一个crtc下会有两个plane。即当前34,和后面的35.只是fb会不同。primary的fb是drmModeAddFb2创建,而另一个Cursor是创建鼠标,内核创建的。
  formats: XR15 RG16 XR24 AR24
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 1
        17 FB_ID:
                flags: object
                value: 0
        18 IN_FENCE_FD:
                flags: signed range
                values: -1 2147483647
                value: -1
        20 CRTC_ID:
                flags: object
                value: 0
        13 CRTC_X:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        14 CRTC_Y:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        15 CRTC_W:
                flags: range
                values: 0 2147483647
                value: 1920
        16 CRTC_H:
                flags: range
                values: 0 2147483647
                value: 1080
        9 SRC_X:
                flags: range
                values: 0 4294967295
                value: 0
        10 SRC_Y:
                flags: range
                values: 0 4294967295
                value: 0
        11 SRC_W:
                flags: range
                values: 0 4294967295
                value: 125829120
        12 SRC_H:
                flags: range
                values: 0 4294967295
                value: 70778880
        21 FB_DAMAGE_CLIPS:
                flags: blob
                blobs:

                value:
35      0       0       0,0             0,0     0               0x00000001
  formats: AR24
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 2
        17 FB_ID:
                flags: object
                value: 0
        18 IN_FENCE_FD:
                flags: signed range
                values: -1 2147483647
                value: -1
        20 CRTC_ID:
                flags: object
                value: 0
        13 CRTC_X:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        14 CRTC_Y:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        15 CRTC_W:
                flags: range
                values: 0 2147483647
                value: 0
        16 CRTC_H:
                flags: range
                values: 0 2147483647
                value: 0
        9 SRC_X:

上述输出的crtc中fb在什么时候设置?

答:上述crtc的fb是primary的。其在drm_mode_setcrtc->__drm_mode_set_config_internal函数设置  :

static int __drm_mode_set_config_internal(struct drm_mode_set *set,
					  struct drm_modeset_acquire_ctx *ctx)
{	
.....
    if (ret == 0) {
		struct drm_plane *plane = crtc->primary;

		plane->crtc = fb ? crtc : NULL; //设置crtc
		plane->fb = fb;    //设置fb
	}
.....
}

另外一个cursor的在drm_mode_cursor2_ioctl->drm_mode_cursor_common->drm_mode_cursor_universal-> __setplane_internal:

static int __setplane_internal(struct drm_plane *plane,
			       struct drm_crtc *crtc,
			       struct drm_framebuffer *fb,
			       int32_t crtc_x, int32_t crtc_y,
			       uint32_t crtc_w, uint32_t crtc_h,
			       /* src_{x,y,w,h} values are 16.16 fixed point */
			       uint32_t src_x, uint32_t src_y,
			       uint32_t src_w, uint32_t src_h,
			       struct drm_modeset_acquire_ctx *ctx)

{

  ....
	plane->old_fb = plane->fb;
	ret = plane->funcs->update_plane(plane, crtc, fb,
					 crtc_x, crtc_y, crtc_w, crtc_h,
					 src_x, src_y, src_w, src_h, ctx);
	if (!ret) {
		plane->crtc = crtc; //设置crtc
		plane->fb = fb;  //设置fb
		drm_framebuffer_get(plane->fb);
	} else {
		plane->old_fb = NULL;
	}
   ...
}

上述输出的plane中的crtc和fb。以及possible_crtcs在哪里设置?

1:crtc和fb就是上面讲的。分别在primary和cursor两个plane中设置。

2:possible_crts在drm_crtc_init_with_planes: 

int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
                              struct drm_plane *primary,
                              struct drm_plane *cursor,
                              const struct drm_crtc_funcs *funcs,
                              const char *name, ...)
{
        struct drm_mode_config *config = &dev->mode_config;
        int ret;

.....
        crtc->primary = primary;
        crtc->cursor = cursor;
        if (primary && !primary->possible_crtcs)
                primary->possible_crtcs = drm_crtc_mask(crtc);
        if (cursor && !cursor->possible_crtcs)
                cursor->possible_crtcs = drm_crtc_mask(crtc);

.....
}

总结:内核驱动中需要建立connecotr和encoder的关系。encoder和crtc的关系。也会建立了crtc和plane的关系。用户通过drmModeSetCrtc将 这三者串起来。

drmModeSetCrtc函数:

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);
}

   

内核对应的函数drm_mode_setcrtc做的事情:

1:通过best_encoder设置connector的encoder。

2:设置encoder的crtc。

3:设置crtc下primary plane的fb和crtc。

  由于一个connector可多个备选的encoder,一个encoder有备选的多个crtc,而一个crtc的两个plane是唯一的。因此需要最终用户通过libdrm来决定。

设置显示之后:下面摘取通过命令

modetest -M vmwgfx -a -s 36@38:1280x768  -P 34@38:1280x768 -Ftiles让显示器显示后的输出。

root@wzm-virtual-machine:/home/wzm# modetest  -M vmwgfx -c 
Connectors:
id      encoder status          name            size (mm)       modes   encoders
36      37      connected       Virtual-1       0x0             25      37
modes:
   index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 800x600 60.00 800 850 900 950 600 650 700 750 42750 flags: nhsync, pvsync; type: preferred, driver
  #1 3840x2400 59.97 3840 3888 3920 4000 2400 2403 2409 2469 592250 flags: phsync, nvsync; type: driver
  #2 3840x2160 59.97 3840 3888 3920 4000 2160 2163 2168 2222 533000 flags: phsync, nvsync; type: driver
  #3 2880x1800 59.95 2880 2928 2960 3040 1800 1803 1809 1852 337500 flags: phsync, nvsync; type: driver
  #4 2560x1600 59.99 2560 2752 3032 3504 1600 1603 1609 1658 348500 flags: nhsync, pvsync; type: driver
  #5 2560x1440 59.95 2560 2608 2640 2720 1440 1443 1448 1481 241500 flags: phsync, nvsync; type: driver
  #6 1920x1440 60.00 1920 2048 2256 2600 1440 1441 1444 1500 234000 flags: nhsync, pvsync; type: driver
  #7 1856x1392 60.00 1856 1952 2176 2528 1392 1393 1396 1439 218250 flags: nhsync, pvsync; type: driver
  #8 1792x1344 60.00 1792 1920 2120 2448 1344 1345 1348 1394 204750 flags: nhsync, pvsync; type: driver
  #9 1920x1200 59.88 1920 2056 2256 2592 1200 1203 1209 1245 193250 flags: nhsync, pvsync; type: driver
  #10 1920x1080 59.96 1920 2048 2248 2576 1080 1083 1088 1120 173000 flags: nhsync, pvsync; type: driver
  #11 1600x1200 60.00 1600 1664 1856 2160 1200 1201 1204 1250 162000 flags: phsync, pvsync; type: driver
  #12 1680x1050 59.95 1680 1784 1960 2240 1050 1053 1059 1089 146250 flags: nhsync, pvsync; type: driver
  #13 1400x1050 59.98 1400 1488 1632 1864 1050 1053 1057 1089 121750 flags: nhsync, pvsync; type: driver
  #14 1280x1024 60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, pvsync; type: driver
  #15 1440x900 59.89 1440 1520 1672 1904 900 903 909 934 106500 flags: nhsync, pvsync; type: driver
  #16 1280x960 60.00 1280 1376 1488 1800 960 961 964 1000 108000 flags: phsync, pvsync; type: driver
  #17 1360x768 60.02 1360 1424 1536 1792 768 771 777 795 85500 flags: phsync, pvsync; type: driver
  #18 1280x800 59.81 1280 1352 1480 1680 800 803 809 831 83500 flags: phsync, nvsync; type: driver
  #19 1152x864 75.00 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, pvsync; type: driver
  #20 1280x768 59.87 1280 1344 1472 1664 768 771 778 798 79500 flags: nhsync, pvsync; type: driver
  #21 1280x720 59.86 1280 1344 1472 1664 720 723 728 748 74500 flags: nhsync, pvsync; type: driver
  #22 1024x768 60.00 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, nvsync; type: driver
  #23 800x600 60.32 800 840 968 1056 600 601 605 628 40000 flags: phsync, pvsync; type: driver
  #24 640x480 59.94 640 656 752 800 480 489 492 525 25175 flags: nhsync, nvsync; type: driver
props:
	2 DPMS:
		xx
		xx

41      0       disconnected    Virtual-2       0x0             25      42
  modes:
        index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 800x600 60.00 800 850 900 950 600 650 700 750 42750 flags: nhsync, pvsync; type: preferred, driver
.....


root@wzm-virtual-machine:/home/wzm# modetest  -M vmwgfx -e
Encoders:
id	crtc	type	possible crtcs	possible clones	
37	38	Virtual	0x00000001	0x00000001
42	0	Virtual	0x00000002	0x00000002
47	0	Virtual	0x00000004	0x00000004
52	0	Virtual	0x00000008	0x00000008
57	0	Virtual	0x00000010	0x00000010
62	0	Virtual	0x00000020	0x00000020
67	0	Virtual	0x00000040	0x00000040
72	0	Virtual	0x00000080	0x00000080


root@wzm-virtual-machine:/home/wzm# modetest  -M vmwgfx -p
CRTCs:
id      fb      pos     size
38      75      (0,0)   (1280x768)
  #0 1280x768 59.87 1280 1344 1472 1664 768 771 778 798 79500 flags: nhsync, pvsync; type: driver
  props:
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0
43      0       (0,0)   (0x0)
  #0  -nan 0 0 0 0 0 0 0 0 0 flags: ; type: 
  props:
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0
.....

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
34      38      75      0,0             0,0     0               0x00000001  //primary
  formats: XR15 RG16 XR24 AR24
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 1
35      38      82      0,0             0,0     0               0x00000001   //鼠标,两者的区别是fb不同。
  formats: AR24
  props:
        8 type:
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 2

整个流程

modetest,linux,驱动开发

 文章来源地址https://www.toymoban.com/news/detail-739505.html

到了这里,关于modetest工具测试(linux-5.10)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【IMX6ULL驱动开发学习】10.Linux I2C驱动实战:AT24C02驱动设计流程

    前情回顾:【IMX6ULL驱动开发学习】09.Linux之I2C框架简介和驱动程序模板_阿龙还在写代码的博客-CSDN博客 目录 一、修改设备树(设备树用来指定引脚资源) 二、编写驱动 2.1 i2c_drv_read 2.2 i2c_drv_write 2.3 完整驱动程序 三、上机测试 放在哪个I2C控制器下面 AT24C02的I2C设备地址(查

    2024年02月11日
    浏览(53)
  • 5.10 Vue配置路由(vue-router)

    官方网站:https://v3.router.vuejs.org/zh/installation Vue Router 是 Vue.js 官方提供的一种路由管理工具,它可以帮助开发者管理 Vue.js 应用程序的路由,并实现路由跳转、参数传递、嵌套路由等功能。Vue Router 可以将一个单页面应用分成多个视图,在不同的路由之间进行切换,从而实现了

    2024年02月08日
    浏览(48)
  • 5.10晚间黄金CPI精准分析及多空交易策略

    ====近期有哪些消息面影响黄金走势?本周黄金多空该如何研判?==== ​黄金消息面解析:周三(5月10日)亚欧盘中, 现货黄金震荡下跌 ,现报2030 美元 /盎司,稍早一度触及2038美元/盎司高点。美联储理事杰斐逊周二表示,美国经济正在以一种“有序的方式”放缓,而纽约联

    2024年02月06日
    浏览(77)
  • Windows 10驱动开发入门(五):创建虚拟显示器 Indirect Display驱动开发

    在开发或者办公中,越大的屏幕看起来就显示越舒服了,通常我们的做法是有两块屏幕,这样显示的内容就变多了,可以很容易提高办公的效率。 在设置中 显示 中,如果我们有两块屏幕,在显示器中自然的会出现两个,在其中可以对两块屏幕进行相应的设置。 在这个驱动中

    2023年04月16日
    浏览(42)
  • 【敏捷开发】测试驱动开发(TDD)

    测试驱动开发(Test-Driven Development,简称TDD)是敏捷开发模式中的一项核心实践和技术,也是一种设计方法论。TDD有别于以往的“先编码,后测试”的开发模式,要求在设计与编码之前,先编写测试脚本或设计测试用例。 敏捷开发大师Kent Beck在1996年提出了极限编程(Extreme

    2024年02月14日
    浏览(36)
  • 什么是BDD测试(行为驱动开发测试)?

    BDD (Behavior Driven Development) 测 试 ,即  行为驱动开发测试 , 是一种基于用户行为和需求的软件测试方法。 通过将测试用例编写为自然语言脚本,BDD测试可以促进业务需求、开发和测试团队之间的沟通和协作,从而提高代码的可读性、可维护性和可重复性。 BDD测试的优点

    2024年03月27日
    浏览(41)
  • 测试先行:探索测试驱动开发的深层价值

    在软件开发的世界中,如何确保代码的质量和可维护性始终是一个核心议题。测试驱动开发(TDD)为此提供了一个答案。与传统的开发方法相比,TDD鼓励开发者从用户的角度出发,先定义期望的结果,再进行实际的开发。这种方法不仅可以确保代码满足预期的需求,还可以在

    2024年02月11日
    浏览(34)
  • 领域驱动设计&事件驱动框架&命令查询责任分离&测试驱动开发

    领域驱动设计: DDD 事件驱动框架: Event Driven Architecture 命令查询责任分离: CQRS(Command Query Responsibility Segregation) 测试驱动开发: TDD 入口是系统外部客户访问系统内部的端口。常见的入口如http, rpc, 命令行,外部消息(消费kafka,rocketmq或者zk, etcd的通知消息)。 入口的职责:解析外部

    2024年02月04日
    浏览(44)
  • <Linux开发>驱动开发 -Linux MISC 驱动

    <Linux开发>驱动开发 -Linux MISC 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发> -之

    2024年02月13日
    浏览(30)
  • <Linux开发>驱动开发 -之- Linux LCD 驱动

    <Linux开发>驱动开发 -之- Linux LCD 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发>

    2024年02月06日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包