xref: /OK3568_Linux_fs/buildroot/package/weston/0016-backend-drm-Support-virtual-screen-size.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunFrom 2a839667bac950c484e109560cd380af760e3781 Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Jeffy Chen <jeffy.chen@rock-chips.com>
3*4882a593SmuzhiyunDate: Wed, 24 Jun 2020 11:59:42 +0800
4*4882a593SmuzhiyunSubject: [PATCH 16/93] backend-drm: Support virtual screen size
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunSupport setting virtual screen size, for example:
7*4882a593Smuzhiyunexport WESTON_DRM_VIRTUAL_SIZE=1024x768
8*4882a593Smuzhiyun
9*4882a593SmuzhiyunSigned-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
10*4882a593Smuzhiyun---
11*4882a593Smuzhiyun libweston/backend-drm/drm-internal.h |  22 +++++
12*4882a593Smuzhiyun libweston/backend-drm/drm.c          |  22 ++++-
13*4882a593Smuzhiyun libweston/backend-drm/kms.c          | 115 ++++++++++++++++++++++-----
14*4882a593Smuzhiyun libweston/backend-drm/modes.c        |  22 ++++-
15*4882a593Smuzhiyun 4 files changed, 155 insertions(+), 26 deletions(-)
16*4882a593Smuzhiyun
17*4882a593Smuzhiyundiff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h
18*4882a593Smuzhiyunindex ec8bf0e..af82922 100644
19*4882a593Smuzhiyun--- a/libweston/backend-drm/drm-internal.h
20*4882a593Smuzhiyun+++ b/libweston/backend-drm/drm-internal.h
21*4882a593Smuzhiyun@@ -166,6 +166,7 @@ enum wdrm_plane_property {
22*4882a593Smuzhiyun 	WDRM_PLANE_IN_FENCE_FD,
23*4882a593Smuzhiyun 	WDRM_PLANE_FB_DAMAGE_CLIPS,
24*4882a593Smuzhiyun 	WDRM_PLANE_ZPOS,
25*4882a593Smuzhiyun+	WDRM_PLANE_FEATURE,
26*4882a593Smuzhiyun 	WDRM_PLANE__COUNT
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun@@ -179,6 +180,15 @@ enum wdrm_plane_type {
30*4882a593Smuzhiyun 	WDRM_PLANE_TYPE__COUNT
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun+/**
34*4882a593Smuzhiyun+ * Possible values for the WDRM_PLANE_FEATURE property.
35*4882a593Smuzhiyun+ */
36*4882a593Smuzhiyun+enum wdrm_plane_feature {
37*4882a593Smuzhiyun+	WDRM_PLANE_FEATURE_SCALE = 0,
38*4882a593Smuzhiyun+	WDRM_PLANE_FEATURE_ALPHA,
39*4882a593Smuzhiyun+	WDRM_PLANE_FEATURE__COUNT
40*4882a593Smuzhiyun+};
41*4882a593Smuzhiyun+
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun  * List of properties attached to a DRM connector
44*4882a593Smuzhiyun  */
45*4882a593Smuzhiyun@@ -349,6 +359,9 @@ struct drm_backend {
46*4882a593Smuzhiyun 	drm_head_match_t *head_matches;
47*4882a593Smuzhiyun 	struct drm_head *primary_head;
48*4882a593Smuzhiyun 	struct wl_listener output_create_listener;
49*4882a593Smuzhiyun+
50*4882a593Smuzhiyun+	int virtual_width;
51*4882a593Smuzhiyun+	int virtual_height;
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun struct drm_mode {
55*4882a593Smuzhiyun@@ -508,6 +521,8 @@ struct drm_plane {
56*4882a593Smuzhiyun 	struct wl_list link;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun 	struct weston_drm_format_array formats;
59*4882a593Smuzhiyun+
60*4882a593Smuzhiyun+	bool can_scale;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun struct drm_connector {
64*4882a593Smuzhiyun@@ -613,6 +628,9 @@ struct drm_output {
65*4882a593Smuzhiyun 	submit_frame_cb virtual_submit_frame;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun 	bool state_invalid;
68*4882a593Smuzhiyun+
69*4882a593Smuzhiyun+	/* The dummy framebuffer for SET_CRTC. */
70*4882a593Smuzhiyun+	struct drm_fb *fb_dummy;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun void
74*4882a593Smuzhiyun@@ -726,6 +744,10 @@ uint64_t
75*4882a593Smuzhiyun drm_property_get_value(struct drm_property_info *info,
76*4882a593Smuzhiyun 		       const drmModeObjectProperties *props,
77*4882a593Smuzhiyun 		       uint64_t def);
78*4882a593Smuzhiyun+bool
79*4882a593Smuzhiyun+drm_property_has_feature(struct drm_property_info *infos,
80*4882a593Smuzhiyun+			 const drmModeObjectProperties *props,
81*4882a593Smuzhiyun+			 enum wdrm_plane_feature feature);
82*4882a593Smuzhiyun uint64_t *
83*4882a593Smuzhiyun drm_property_get_range_values(struct drm_property_info *info,
84*4882a593Smuzhiyun 			      const drmModeObjectProperties *props);
85*4882a593Smuzhiyundiff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
86*4882a593Smuzhiyunindex f5ac1b6..a2f215f 100644
87*4882a593Smuzhiyun--- a/libweston/backend-drm/drm.c
88*4882a593Smuzhiyun+++ b/libweston/backend-drm/drm.c
89*4882a593Smuzhiyun@@ -331,6 +331,11 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
90*4882a593Smuzhiyun 		output->state_last = NULL;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun+	if (output->fb_dummy) {
94*4882a593Smuzhiyun+		drm_fb_unref(output->fb_dummy);
95*4882a593Smuzhiyun+		output->fb_dummy = NULL;
96*4882a593Smuzhiyun+	}
97*4882a593Smuzhiyun+
98*4882a593Smuzhiyun 	if (output->destroy_pending) {
99*4882a593Smuzhiyun 		output->destroy_pending = false;
100*4882a593Smuzhiyun 		output->disable_pending = false;
101*4882a593Smuzhiyun@@ -411,6 +416,7 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
102*4882a593Smuzhiyun 	struct drm_property_info *damage_info =
103*4882a593Smuzhiyun 		&scanout_plane->props[WDRM_PLANE_FB_DAMAGE_CLIPS];
104*4882a593Smuzhiyun 	struct drm_backend *b = device->backend;
105*4882a593Smuzhiyun+	struct drm_mode *mode;
106*4882a593Smuzhiyun 	struct drm_fb *fb;
107*4882a593Smuzhiyun 	pixman_region32_t scanout_damage;
108*4882a593Smuzhiyun 	pixman_box32_t *rects;
109*4882a593Smuzhiyun@@ -454,10 +460,11 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
110*4882a593Smuzhiyun 	scanout_state->src_w = fb->width << 16;
111*4882a593Smuzhiyun 	scanout_state->src_h = fb->height << 16;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun+	mode = to_drm_mode(output->base.current_mode);
114*4882a593Smuzhiyun 	scanout_state->dest_x = 0;
115*4882a593Smuzhiyun 	scanout_state->dest_y = 0;
116*4882a593Smuzhiyun-	scanout_state->dest_w = output->base.current_mode->width;
117*4882a593Smuzhiyun-	scanout_state->dest_h = output->base.current_mode->height;
118*4882a593Smuzhiyun+	scanout_state->dest_w = mode->mode_info.hdisplay;
119*4882a593Smuzhiyun+	scanout_state->dest_h = mode->mode_info.vdisplay;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun 	pixman_region32_subtract(&c->primary_plane.damage,
122*4882a593Smuzhiyun 				 &c->primary_plane.damage, damage);
123*4882a593Smuzhiyun@@ -521,7 +528,7 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun 	weston_compositor_read_presentation_clock(b->compositor, &now);
126*4882a593Smuzhiyun 	now_ms = timespec_to_msec(&now);
127*4882a593Smuzhiyun-	if (now_ms < b->last_resize_ms + DRM_RESIZE_FREEZE_MS) {
128*4882a593Smuzhiyun+	if (now_ms < b->last_resize_ms + b->resize_freeze_ms) {
129*4882a593Smuzhiyun 		/* Resize fullscreen/maxmium views(not always success) */
130*4882a593Smuzhiyun 		if (now_ms < b->last_resize_ms + DRM_RESIZE_FREEZE_MS)
131*4882a593Smuzhiyun 			wl_signal_emit(&b->compositor->output_resized_signal,
132*4882a593Smuzhiyun@@ -879,6 +886,11 @@ drm_plane_create(struct drm_device *device, const drmModePlane *kplane)
133*4882a593Smuzhiyun 				       props,
134*4882a593Smuzhiyun 				       WDRM_PLANE_TYPE__COUNT);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun+	plane->can_scale =
137*4882a593Smuzhiyun+		drm_property_has_feature(plane->props,
138*4882a593Smuzhiyun+					 props,
139*4882a593Smuzhiyun+					 WDRM_PLANE_FEATURE_SCALE);
140*4882a593Smuzhiyun+
141*4882a593Smuzhiyun 	zpos_range_values =
142*4882a593Smuzhiyun 		drm_property_get_range_values(&plane->props[WDRM_PLANE_ZPOS],
143*4882a593Smuzhiyun 					      props);
144*4882a593Smuzhiyun@@ -3420,6 +3432,10 @@ drm_backend_create(struct weston_compositor *compositor,
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun 	b->head_matches = drm_head_matches[head_mode];
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun+	buf = getenv("WESTON_DRM_VIRTUAL_SIZE");
149*4882a593Smuzhiyun+	if (buf)
150*4882a593Smuzhiyun+		sscanf(buf, "%dx%d", &b->virtual_width, &b->virtual_height);
151*4882a593Smuzhiyun+
152*4882a593Smuzhiyun 	buf = getenv("WESTON_DRM_RESIZE_FREEZE_MS");
153*4882a593Smuzhiyun 	if (buf)
154*4882a593Smuzhiyun 		b->resize_freeze_ms = atoi(buf);
155*4882a593Smuzhiyundiff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
156*4882a593Smuzhiyunindex c7dc2f8..0008e83 100644
157*4882a593Smuzhiyun--- a/libweston/backend-drm/kms.c
158*4882a593Smuzhiyun+++ b/libweston/backend-drm/kms.c
159*4882a593Smuzhiyun@@ -56,6 +56,15 @@ struct drm_property_enum_info plane_type_enums[] = {
160*4882a593Smuzhiyun 	},
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun+struct drm_property_enum_info plane_feature_enums[] = {
164*4882a593Smuzhiyun+	[WDRM_PLANE_FEATURE_SCALE] = {
165*4882a593Smuzhiyun+		.name = "scale",
166*4882a593Smuzhiyun+	},
167*4882a593Smuzhiyun+	[WDRM_PLANE_FEATURE_ALPHA] = {
168*4882a593Smuzhiyun+		.name = "alpha",
169*4882a593Smuzhiyun+	},
170*4882a593Smuzhiyun+};
171*4882a593Smuzhiyun+
172*4882a593Smuzhiyun const struct drm_property_info plane_props[] = {
173*4882a593Smuzhiyun 	[WDRM_PLANE_TYPE] = {
174*4882a593Smuzhiyun 		.name = "type",
175*4882a593Smuzhiyun@@ -76,6 +85,11 @@ const struct drm_property_info plane_props[] = {
176*4882a593Smuzhiyun 	[WDRM_PLANE_IN_FENCE_FD] = { .name = "IN_FENCE_FD" },
177*4882a593Smuzhiyun 	[WDRM_PLANE_FB_DAMAGE_CLIPS] = { .name = "FB_DAMAGE_CLIPS" },
178*4882a593Smuzhiyun 	[WDRM_PLANE_ZPOS] = { .name = "zpos" },
179*4882a593Smuzhiyun+	[WDRM_PLANE_FEATURE] = {
180*4882a593Smuzhiyun+		.name = "FEATURE",
181*4882a593Smuzhiyun+		.enum_values = plane_feature_enums,
182*4882a593Smuzhiyun+		.num_enum_values = WDRM_PLANE_FEATURE__COUNT,
183*4882a593Smuzhiyun+	},
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun struct drm_property_enum_info dpms_state_enums[] = {
187*4882a593Smuzhiyun@@ -217,6 +231,31 @@ drm_property_get_value(struct drm_property_info *info,
188*4882a593Smuzhiyun 	return def;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun+bool
192*4882a593Smuzhiyun+drm_property_has_feature(struct drm_property_info *infos,
193*4882a593Smuzhiyun+			 const drmModeObjectProperties *props,
194*4882a593Smuzhiyun+			 enum wdrm_plane_feature feature)
195*4882a593Smuzhiyun+{
196*4882a593Smuzhiyun+	struct drm_property_info *info = &infos[WDRM_PLANE_FEATURE];
197*4882a593Smuzhiyun+	unsigned int i;
198*4882a593Smuzhiyun+
199*4882a593Smuzhiyun+	if (info->prop_id == 0 ||
200*4882a593Smuzhiyun+	    feature >= info->num_enum_values ||
201*4882a593Smuzhiyun+	    !info->enum_values[feature].valid)
202*4882a593Smuzhiyun+		return false;
203*4882a593Smuzhiyun+
204*4882a593Smuzhiyun+	for (i = 0; i < props->count_props; i++) {
205*4882a593Smuzhiyun+		if (props->props[i] != info->prop_id)
206*4882a593Smuzhiyun+			continue;
207*4882a593Smuzhiyun+
208*4882a593Smuzhiyun+		if (props->prop_values[i] &
209*4882a593Smuzhiyun+		    (1LL << info->enum_values[feature].value))
210*4882a593Smuzhiyun+			return true;
211*4882a593Smuzhiyun+	}
212*4882a593Smuzhiyun+
213*4882a593Smuzhiyun+	return false;
214*4882a593Smuzhiyun+}
215*4882a593Smuzhiyun+
216*4882a593Smuzhiyun /**
217*4882a593Smuzhiyun  * Get the current range values of a KMS property
218*4882a593Smuzhiyun  *
219*4882a593Smuzhiyun@@ -337,9 +376,11 @@ drm_property_info_populate(struct drm_device *device,
220*4882a593Smuzhiyun 		}
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun 		if (info[j].num_enum_values == 0 &&
223*4882a593Smuzhiyun-		    (prop->flags & DRM_MODE_PROP_ENUM)) {
224*4882a593Smuzhiyun+		    (prop->flags & DRM_MODE_PROP_ENUM ||
225*4882a593Smuzhiyun+		     prop->flags & DRM_MODE_PROP_BITMASK)) {
226*4882a593Smuzhiyun 			weston_log("DRM: expected property %s to not be an"
227*4882a593Smuzhiyun-			           " enum, but it is; ignoring\n", prop->name);
228*4882a593Smuzhiyun+			           " enum or bitmask, but it is; ignoring\n",
229*4882a593Smuzhiyun+				   prop->name);
230*4882a593Smuzhiyun 			drmModeFreeProperty(prop);
231*4882a593Smuzhiyun 			continue;
232*4882a593Smuzhiyun 		}
233*4882a593Smuzhiyun@@ -360,9 +401,11 @@ drm_property_info_populate(struct drm_device *device,
234*4882a593Smuzhiyun 			continue;
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun-		if (!(prop->flags & DRM_MODE_PROP_ENUM)) {
238*4882a593Smuzhiyun-			weston_log("DRM: expected property %s to be an enum,"
239*4882a593Smuzhiyun-				   " but it is not; ignoring\n", prop->name);
240*4882a593Smuzhiyun+		if (!(prop->flags & DRM_MODE_PROP_ENUM ||
241*4882a593Smuzhiyun+		      prop->flags & DRM_MODE_PROP_BITMASK)) {
242*4882a593Smuzhiyun+			weston_log("DRM: expected property %s to be an enum or "
243*4882a593Smuzhiyun+				   "bitmask, but it is not; ignoring\n",
244*4882a593Smuzhiyun+				   prop->name);
245*4882a593Smuzhiyun 			drmModeFreeProperty(prop);
246*4882a593Smuzhiyun 			info[j].prop_id = 0;
247*4882a593Smuzhiyun 			continue;
248*4882a593Smuzhiyun@@ -639,6 +682,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
249*4882a593Smuzhiyun 	int n_conn = 0;
250*4882a593Smuzhiyun 	struct timespec now;
251*4882a593Smuzhiyun 	int ret = 0;
252*4882a593Smuzhiyun+	bool scaling;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun 	wl_list_for_each(head, &output->base.head_list, base.output_link) {
255*4882a593Smuzhiyun 		assert(n_conn < MAX_CLONED_CONNECTORS);
256*4882a593Smuzhiyun@@ -686,30 +730,36 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
257*4882a593Smuzhiyun 	if (!scanout_state || !scanout_state->fb)
258*4882a593Smuzhiyun 		return 0;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun-	/* The legacy SetCrtc API doesn't allow us to do scaling, and the
261*4882a593Smuzhiyun-	 * legacy PageFlip API doesn't allow us to do clipping either. */
262*4882a593Smuzhiyun-	assert(scanout_state->src_x == 0);
263*4882a593Smuzhiyun-	assert(scanout_state->src_y == 0);
264*4882a593Smuzhiyun-	assert(scanout_state->src_w ==
265*4882a593Smuzhiyun-		(unsigned) (output->base.current_mode->width << 16));
266*4882a593Smuzhiyun-	assert(scanout_state->src_h ==
267*4882a593Smuzhiyun-		(unsigned) (output->base.current_mode->height << 16));
268*4882a593Smuzhiyun-	assert(scanout_state->dest_x == 0);
269*4882a593Smuzhiyun-	assert(scanout_state->dest_y == 0);
270*4882a593Smuzhiyun-	assert(scanout_state->dest_w == scanout_state->src_w >> 16);
271*4882a593Smuzhiyun-	assert(scanout_state->dest_h == scanout_state->src_h >> 16);
272*4882a593Smuzhiyun 	/* The legacy SetCrtc API doesn't support fences */
273*4882a593Smuzhiyun 	assert(scanout_state->in_fence_fd == -1);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun 	mode = to_drm_mode(output->base.current_mode);
276*4882a593Smuzhiyun+
277*4882a593Smuzhiyun+	scaling = scanout_state->src_w >> 16 != scanout_state->dest_w ||
278*4882a593Smuzhiyun+		scanout_state->src_h >> 16 != scanout_state->dest_h;
279*4882a593Smuzhiyun+
280*4882a593Smuzhiyun 	if (output->state_invalid ||
281*4882a593Smuzhiyun-	    !scanout_plane->state_cur->fb ||
282*4882a593Smuzhiyun-	    scanout_plane->state_cur->fb->strides[0] !=
283*4882a593Smuzhiyun-	    scanout_state->fb->strides[0]) {
284*4882a593Smuzhiyun+	    !scanout_plane->state_cur->fb) {
285*4882a593Smuzhiyun+		int fb_id = scanout_state->fb->fb_id;
286*4882a593Smuzhiyun+
287*4882a593Smuzhiyun+		/* Use a dummy fb for initial mode setting */
288*4882a593Smuzhiyun+		if (!output->fb_dummy) {
289*4882a593Smuzhiyun+			output->fb_dummy =
290*4882a593Smuzhiyun+				drm_fb_create_dumb(device,
291*4882a593Smuzhiyun+						   mode->mode_info.hdisplay,
292*4882a593Smuzhiyun+						   mode->mode_info.vdisplay,
293*4882a593Smuzhiyun+						   output->gbm_format);
294*4882a593Smuzhiyun+			if (!output->fb_dummy) {
295*4882a593Smuzhiyun+				weston_log("failed to create fb_dummy\n");
296*4882a593Smuzhiyun+				goto err;
297*4882a593Smuzhiyun+			}
298*4882a593Smuzhiyun+		}
299*4882a593Smuzhiyun+
300*4882a593Smuzhiyun+		if (n_conn == 1 || scaling)
301*4882a593Smuzhiyun+			fb_id = output->fb_dummy->fb_id;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun 		ret = drmModeSetCrtc(device->drm.fd, crtc->crtc_id,
304*4882a593Smuzhiyun-				     scanout_state->fb->fb_id,
305*4882a593Smuzhiyun-				     0, 0,
306*4882a593Smuzhiyun+				     fb_id, 0, 0,
307*4882a593Smuzhiyun 				     connectors, n_conn,
308*4882a593Smuzhiyun 				     &mode->mode_info);
309*4882a593Smuzhiyun 		if (ret) {
310*4882a593Smuzhiyun@@ -720,6 +770,27 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
311*4882a593Smuzhiyun 		output->state_invalid = false;
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun+	if (scaling && !output->scanout_plane->can_scale) {
315*4882a593Smuzhiyun+		weston_log("Couldn't do scaling on output %s\n",
316*4882a593Smuzhiyun+			   output->base.name);
317*4882a593Smuzhiyun+		weston_output_finish_frame(&output->base, NULL,
318*4882a593Smuzhiyun+					   WP_PRESENTATION_FEEDBACK_INVALID);
319*4882a593Smuzhiyun+		return 0;
320*4882a593Smuzhiyun+	}
321*4882a593Smuzhiyun+
322*4882a593Smuzhiyun+	ret = drmModeSetPlane(device->drm.fd,
323*4882a593Smuzhiyun+			      scanout_state->plane->plane_id,
324*4882a593Smuzhiyun+			      crtc->crtc_id,
325*4882a593Smuzhiyun+			      scanout_state->fb->fb_id, 0,
326*4882a593Smuzhiyun+			      scanout_state->dest_x, scanout_state->dest_y,
327*4882a593Smuzhiyun+			      scanout_state->dest_w, scanout_state->dest_h,
328*4882a593Smuzhiyun+			      scanout_state->src_x, scanout_state->src_y,
329*4882a593Smuzhiyun+			      scanout_state->src_w, scanout_state->src_h);
330*4882a593Smuzhiyun+	if (ret) {
331*4882a593Smuzhiyun+		weston_log("set plane failed: %s\n", strerror(errno));
332*4882a593Smuzhiyun+		goto err;
333*4882a593Smuzhiyun+	}
334*4882a593Smuzhiyun+
335*4882a593Smuzhiyun 	pinfo = scanout_state->fb->format;
336*4882a593Smuzhiyun 	drm_debug(backend, "\t[CRTC:%u, PLANE:%u] FORMAT: %s\n",
337*4882a593Smuzhiyun 			   crtc->crtc_id, scanout_state->plane->plane_id,
338*4882a593Smuzhiyundiff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c
339*4882a593Smuzhiyunindex ae3a35d..7e7865b 100644
340*4882a593Smuzhiyun--- a/libweston/backend-drm/modes.c
341*4882a593Smuzhiyun+++ b/libweston/backend-drm/modes.c
342*4882a593Smuzhiyun@@ -398,6 +398,7 @@ drm_refresh_rate_mHz(const drmModeModeInfo *info)
343*4882a593Smuzhiyun static struct drm_mode *
344*4882a593Smuzhiyun drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun+	struct drm_backend *b = to_drm_backend(output->base.compositor);
347*4882a593Smuzhiyun 	struct drm_mode *mode;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun 	mode = malloc(sizeof *mode);
350*4882a593Smuzhiyun@@ -408,6 +409,11 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
351*4882a593Smuzhiyun 	mode->base.width = info->hdisplay;
352*4882a593Smuzhiyun 	mode->base.height = info->vdisplay;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun+	if (b->virtual_width && b->virtual_height) {
355*4882a593Smuzhiyun+		mode->base.width = b->virtual_width;
356*4882a593Smuzhiyun+		mode->base.height = b->virtual_height;
357*4882a593Smuzhiyun+	}
358*4882a593Smuzhiyun+
359*4882a593Smuzhiyun 	mode->base.refresh = drm_refresh_rate_mHz(info);
360*4882a593Smuzhiyun 	mode->mode_info = *info;
361*4882a593Smuzhiyun 	mode->blob_id = 0;
362*4882a593Smuzhiyun@@ -454,20 +460,34 @@ drm_output_print_modes(struct drm_output *output)
363*4882a593Smuzhiyun 	struct weston_mode *m;
364*4882a593Smuzhiyun 	struct drm_mode *dm;
365*4882a593Smuzhiyun 	const char *aspect_ratio;
366*4882a593Smuzhiyun+	bool virtual_size = false;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun 	wl_list_for_each(m, &output->base.mode_list, link) {
369*4882a593Smuzhiyun 		dm = to_drm_mode(m);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun 		aspect_ratio = aspect_ratio_to_string(m->aspect_ratio);
372*4882a593Smuzhiyun 		weston_log_continue(STAMP_SPACE "%dx%d@%.1f%s%s%s, %.1f MHz\n",
373*4882a593Smuzhiyun-				    m->width, m->height, m->refresh / 1000.0,
374*4882a593Smuzhiyun+				    dm->mode_info.hdisplay,
375*4882a593Smuzhiyun+				    dm->mode_info.vdisplay,
376*4882a593Smuzhiyun+				    m->refresh / 1000.0,
377*4882a593Smuzhiyun 				    aspect_ratio,
378*4882a593Smuzhiyun 				    m->flags & WL_OUTPUT_MODE_PREFERRED ?
379*4882a593Smuzhiyun 				    ", preferred" : "",
380*4882a593Smuzhiyun 				    m->flags & WL_OUTPUT_MODE_CURRENT ?
381*4882a593Smuzhiyun 				    ", current" : "",
382*4882a593Smuzhiyun 				    dm->mode_info.clock / 1000.0);
383*4882a593Smuzhiyun+
384*4882a593Smuzhiyun+		if(m->flags & WL_OUTPUT_MODE_CURRENT &&
385*4882a593Smuzhiyun+		   (dm->mode_info.hdisplay != m->width ||
386*4882a593Smuzhiyun+		    dm->mode_info.vdisplay != m->height))
387*4882a593Smuzhiyun+			virtual_size = true;
388*4882a593Smuzhiyun 	}
389*4882a593Smuzhiyun+
390*4882a593Smuzhiyun+	if (virtual_size)
391*4882a593Smuzhiyun+		weston_log("Output %s: using virtual size %dx%d\n",
392*4882a593Smuzhiyun+			   output->base.name,
393*4882a593Smuzhiyun+			   output->base.current_mode->width,
394*4882a593Smuzhiyun+			   output->base.current_mode->height);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun--
399*4882a593Smuzhiyun2.20.1
400*4882a593Smuzhiyun
401