diff mbox series

drm/vmwgfx: Trigger a modeset when the screen moves

Message ID 20240624205951.23343-1-ian.forbes@broadcom.com (mailing list archive)
State New, archived
Headers show
Series drm/vmwgfx: Trigger a modeset when the screen moves | expand

Commit Message

Ian Forbes June 24, 2024, 8:59 p.m. UTC
When multi-monitor is cycled the X,Y position of the Screen Target will
likely change but the resolution will not. We need to trigger a modeset
when this occurs in order to recreate the Screen Target with the correct
X,Y position.

Fixes a bug where multiple displays are shown in a single scrollable
host window rather than in 2+ windows on separate host displays.

Fixes: 426826933109 ("drm/vmwgfx: Filter modes which exceed graphics memory")
Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 29 +++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

Comments

Maaz Mombasawala Aug. 14, 2024, 12:28 a.m. UTC | #1
On 6/24/24 13:59, Ian Forbes wrote:
> When multi-monitor is cycled the X,Y position of the Screen Target will
> likely change but the resolution will not. We need to trigger a modeset
> when this occurs in order to recreate the Screen Target with the correct
> X,Y position.
> 
> Fixes a bug where multiple displays are shown in a single scrollable
> host window rather than in 2+ windows on separate host displays.
> 
> Fixes: 426826933109 ("drm/vmwgfx: Filter modes which exceed graphics memory")
> Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 29 +++++++++++++++++++++++++++-
>  1 file changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index a04e0736318da..9becd71bc93bc 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -877,6 +877,32 @@ vmw_stdu_connector_mode_valid(struct drm_connector *connector,
>  	return MODE_OK;
>  }
>  
> +/*
> + * Trigger a modeset if the X,Y position of the Screen Target changes.
> + * This is needed when multi-mon is cycled. The original Screen Target will have
> + * the same mode but its relative X,Y position in the topology will change.
> + */
> +static int vmw_stdu_connector_atomic_check(struct drm_connector *conn,
> +					   struct drm_atomic_state *state)
> +{
> +	struct drm_connector_state *conn_state;
> +	struct vmw_screen_target_display_unit *du;
> +	struct drm_crtc_state *new_crtc_state;
> +
> +	conn_state = drm_atomic_get_connector_state(state, conn);
> +	du = vmw_connector_to_stdu(conn);
> +
> +	if (!conn_state->crtc)
> +		return 0;
> +
> +	new_crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);

We should be checking for new_crtc_state being NULL here.

> +	if (du->base.gui_x != du->base.set_gui_x ||
> +	    du->base.gui_y != du->base.set_gui_y)
> +		new_crtc_state->mode_changed = true;
> +
> +	return 0;
> +}
> +
>  static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
>  	.dpms = vmw_du_connector_dpms,
>  	.detect = vmw_du_connector_detect,
> @@ -891,7 +917,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
>  static const struct
>  drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
>  	.get_modes = vmw_connector_get_modes,
> -	.mode_valid = vmw_stdu_connector_mode_valid
> +	.mode_valid = vmw_stdu_connector_mode_valid,
> +	.atomic_check = vmw_stdu_connector_atomic_check,
>  };
>  
>  

Maaz Mombasawala <maaz.mombasawala@broadcom.com>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index a04e0736318da..9becd71bc93bc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -877,6 +877,32 @@  vmw_stdu_connector_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
+/*
+ * Trigger a modeset if the X,Y position of the Screen Target changes.
+ * This is needed when multi-mon is cycled. The original Screen Target will have
+ * the same mode but its relative X,Y position in the topology will change.
+ */
+static int vmw_stdu_connector_atomic_check(struct drm_connector *conn,
+					   struct drm_atomic_state *state)
+{
+	struct drm_connector_state *conn_state;
+	struct vmw_screen_target_display_unit *du;
+	struct drm_crtc_state *new_crtc_state;
+
+	conn_state = drm_atomic_get_connector_state(state, conn);
+	du = vmw_connector_to_stdu(conn);
+
+	if (!conn_state->crtc)
+		return 0;
+
+	new_crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+	if (du->base.gui_x != du->base.set_gui_x ||
+	    du->base.gui_y != du->base.set_gui_y)
+		new_crtc_state->mode_changed = true;
+
+	return 0;
+}
+
 static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 	.dpms = vmw_du_connector_dpms,
 	.detect = vmw_du_connector_detect,
@@ -891,7 +917,8 @@  static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 static const struct
 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
 	.get_modes = vmw_connector_get_modes,
-	.mode_valid = vmw_stdu_connector_mode_valid
+	.mode_valid = vmw_stdu_connector_mode_valid,
+	.atomic_check = vmw_stdu_connector_atomic_check,
 };