When setting a mode we not only pass the mode to the hypervisor, but also information on how to map / translate input coordinates for the emulated USB tablet. This input-mapping may change when the mode on *another* crtc changes. This means that sometimes we must do a modeset on other crtc-s then the one being changed to update the input-mapping. Including crtc-s which may be disabled inside the guest (shown as a black window on the host unless closed by the user). With atomic modesetting the mode-info of disabled crtcs gets zeroed yet we need it when updating the input-map to avoid resizing the window as a side effect of a mode_set on another crtc. This commit adds caching of the mode info into out private vbox_crtc struct so that we always have the info at hand when we need it. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- drivers/staging/vboxvideo/vbox_drv.h | 20 +++++++++++++++++++ drivers/staging/vboxvideo/vbox_mode.c | 28 +++++++++++++++------------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/staging/vboxvideo/vbox_drv.h b/drivers/staging/vboxvideo/vbox_drv.h index 6c52cbd9e91e..34c4d7fc6c8e 100644 --- a/drivers/staging/vboxvideo/vbox_drv.h +++ b/drivers/staging/vboxvideo/vbox_drv.h @@ -151,6 +151,26 @@ struct vbox_crtc { bool cursor_enabled; u32 x_hint; u32 y_hint; + /* + * When setting a mode we not only pass the mode to the hypervisor, + * but also information on how to map / translate input coordinates + * for the emulated USB tablet. This input-mapping may change when + * the mode on *another* crtc changes. + * + * This means that sometimes we must do a modeset on other crtc-s then + * the one being changed to update the input-mapping. Including crtc-s + * which may be disabled inside the guest (shown as a black window + * on the host unless closed by the user). + * + * With atomic modesetting the mode-info of disabled crtcs gets zeroed + * yet we need it when updating the input-map to avoid resizing the + * window as a side effect of a mode_set on another crtc. Therefor we + * cache the info of the last mode below. + */ + u32 width; + u32 height; + u32 x; + u32 y; }; struct vbox_encoder { diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c index adb6bcf989d1..e85b27f95def 100644 --- a/drivers/staging/vboxvideo/vbox_mode.c +++ b/drivers/staging/vboxvideo/vbox_mode.c @@ -48,8 +48,7 @@ static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y); * Set a graphics mode. Poke any required values into registers, do an HGSMI * mode set and tell the host we support advanced graphics functions. */ -static void vbox_do_modeset(struct drm_crtc *crtc, - const struct drm_display_mode *mode) +static void vbox_do_modeset(struct drm_crtc *crtc) { struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); struct vbox_private *vbox; @@ -58,12 +57,12 @@ static void vbox_do_modeset(struct drm_crtc *crtc, s32 x_offset, y_offset; vbox = crtc->dev->dev_private; - width = mode->hdisplay ? mode->hdisplay : 640; - height = mode->vdisplay ? mode->vdisplay : 480; + width = vbox_crtc->width ? vbox_crtc->width : 640; + height = vbox_crtc->height ? vbox_crtc->height : 480; bpp = crtc->enabled ? CRTC_FB(crtc)->format->cpp[0] * 8 : 32; pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8; - x_offset = vbox->single_framebuffer ? crtc->x : vbox_crtc->x_hint; - y_offset = vbox->single_framebuffer ? crtc->y : vbox_crtc->y_hint; + x_offset = vbox->single_framebuffer ? vbox_crtc->x : vbox_crtc->x_hint; + y_offset = vbox->single_framebuffer ? vbox_crtc->y : vbox_crtc->y_hint; /* * This is the old way of setting graphics modes. It assumed one screen @@ -82,9 +81,9 @@ static void vbox_do_modeset(struct drm_crtc *crtc, vbox_write_ioport(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED); vbox_write_ioport( VBE_DISPI_INDEX_X_OFFSET, - vbox_crtc->fb_offset % pitch / bpp * 8 + crtc->x); + vbox_crtc->fb_offset % pitch / bpp * 8 + vbox_crtc->x); vbox_write_ioport(VBE_DISPI_INDEX_Y_OFFSET, - vbox_crtc->fb_offset / pitch + crtc->y); + vbox_crtc->fb_offset / pitch + vbox_crtc->y); } flags = VBVA_SCREEN_F_ACTIVE; @@ -93,7 +92,8 @@ static void vbox_do_modeset(struct drm_crtc *crtc, flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0; hgsmi_process_display_info(vbox->guest_pool, vbox_crtc->crtc_id, x_offset, y_offset, - crtc->x * bpp / 8 + crtc->y * pitch, + vbox_crtc->x * bpp / 8 + + vbox_crtc->y * pitch, pitch, width, height, vbox_crtc->blanked ? 0 : bpp, flags); } @@ -149,7 +149,7 @@ static void vbox_crtc_dpms(struct drm_crtc *crtc, int mode) } mutex_lock(&vbox->hw_mutex); - vbox_do_modeset(crtc, &crtc->hwmode); + vbox_do_modeset(crtc); mutex_unlock(&vbox->hw_mutex); } @@ -232,6 +232,10 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, mutex_lock(&vbox->hw_mutex); + vbox_crtc->width = mode->hdisplay; + vbox_crtc->height = mode->vdisplay; + vbox_crtc->x = x; + vbox_crtc->y = y; vbox_crtc->fb_offset = vbox_bo_gpu_offset(bo); /* vbox_do_modeset() checks vbox->single_framebuffer so update it now */ @@ -242,12 +246,12 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, head) { if (crtci == crtc) continue; - vbox_do_modeset(crtci, &crtci->mode); + vbox_do_modeset(crtci); } } vbox_set_view(crtc); - vbox_do_modeset(crtc, mode ? mode : &crtc->mode); + vbox_do_modeset(crtc); if (mode) hgsmi_update_input_mapping(vbox->guest_pool, 0, 0, -- 2.19.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel