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

整个流程

 

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古井无波 2024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值