Commit 3ae2ec34fa3a8aec0471ad49c1941b6b4966f41e

Sebastian Krzyszkowiak 2021-01-31T19:06:37

wayland: Fix transform and scale handling when setting display mode

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 335011c..6fafe18 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -247,6 +247,7 @@ display_handle_geometry(void *data,
     SDL_VideoDisplay *display = data;
 
     display->name = SDL_strdup(model);
+    ((SDL_WaylandOutputData*)display->driverdata)->transform = transform;
 }
 
 static void
@@ -259,18 +260,12 @@ display_handle_mode(void *data,
 {
     SDL_DisplayMode mode;
     SDL_VideoDisplay *display = data;
-
-    SDL_zero(mode);
-    mode.format = SDL_PIXELFORMAT_RGB888;
-    mode.w = width;
-    mode.h = height;
-    mode.refresh_rate = refresh / 1000; // mHz to Hz
-    mode.driverdata = ((SDL_WaylandOutputData*)display->driverdata)->output;
-    SDL_AddDisplayMode(display, &mode);
+    SDL_WaylandOutputData* driverdata = display->driverdata;
 
     if (flags & WL_OUTPUT_MODE_CURRENT) {
-        display->current_mode = mode;
-        display->desktop_mode = mode;
+        driverdata->width = width;
+        driverdata->height = height;
+        driverdata->refresh = refresh;
     }
 }
 
@@ -280,6 +275,23 @@ display_handle_done(void *data,
 {
     /* !!! FIXME: this will fail on any further property changes! */
     SDL_VideoDisplay *display = data;
+    SDL_WaylandOutputData* driverdata = display->driverdata;
+    SDL_DisplayMode mode;
+
+    SDL_zero(mode);
+    mode.format = SDL_PIXELFORMAT_RGB888;
+    mode.w = driverdata->width / driverdata->scale_factor;
+    mode.h = driverdata->height / driverdata->scale_factor;
+    if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
+       mode.w = driverdata->height / driverdata->scale_factor;
+       mode.h = driverdata->width / driverdata->scale_factor;
+    }
+    mode.refresh_rate = driverdata->refresh / 1000; // mHz to Hz
+    mode.driverdata = driverdata->output;
+    SDL_AddDisplayMode(display, &mode);
+    display->current_mode = mode;
+    display->desktop_mode = mode;
+
     SDL_AddVideoDisplay(display, SDL_FALSE);
     wl_output_set_user_data(output, display->driverdata);
     SDL_free(display->name);
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index ea7e140..04083bf 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -90,6 +90,7 @@ typedef struct {
 typedef struct {
     struct wl_output *output;
     float scale_factor;
+    int width, height, refresh, transform;
 } SDL_WaylandOutputData;
 
 #endif /* SDL_waylandvideo_h_ */