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