SDL: wayland: Implement GetDisplayDPI

From 509228c42300f0ee362404d28f50999fa6eaed5e Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Sun, 18 Apr 2021 22:26:27 -0400
Subject: [PATCH] wayland: Implement GetDisplayDPI

---
 src/video/wayland/SDL_waylandvideo.c | 46 ++++++++++++++++++++++++++++
 src/video/wayland/SDL_waylandvideo.h |  2 ++
 2 files changed, 48 insertions(+)

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 381224529..3f66a6771 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -61,6 +61,9 @@ Wayland_VideoInit(_THIS);
 static int
 Wayland_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect);
 
+static int
+Wayland_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
+
 static void
 Wayland_VideoQuit(_THIS);
 
@@ -176,6 +179,7 @@ Wayland_CreateDevice(int devindex)
     device->VideoInit = Wayland_VideoInit;
     device->VideoQuit = Wayland_VideoQuit;
     device->GetDisplayBounds = Wayland_GetDisplayBounds;
+    device->GetDisplayDPI = Wayland_GetDisplayDPI;
     device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
     device->SuspendScreenSaver = Wayland_SuspendScreenSaver;
 
@@ -251,6 +255,8 @@ display_handle_geometry(void *data,
 
     driverdata->x = x;
     driverdata->y = y;
+    driverdata->physical_width = physical_width;
+    driverdata->physical_height = physical_height;
     driverdata->placeholder.name = SDL_strdup(model);
     driverdata->transform = transform;
 }
@@ -309,9 +315,31 @@ display_handle_done(void *data,
     if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
         mode.w = driverdata->height / driverdata->scale_factor;
         mode.h = driverdata->width / driverdata->scale_factor;
+
+        driverdata->hdpi = driverdata->physical_height ?
+            (((float) driverdata->height) * 25.4f / driverdata->physical_height) :
+            0.0f;
+        driverdata->vdpi = driverdata->physical_width ?
+            (((float) driverdata->width) * 25.4f / driverdata->physical_width) :
+            0.0f;
+        driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->height,
+                                                  driverdata->width,
+                                                  ((float) driverdata->physical_height) / 25.4f,
+                                                  ((float) driverdata->physical_width) / 25.4f);
     } else {
         mode.w = driverdata->width / driverdata->scale_factor;
         mode.h = driverdata->height / driverdata->scale_factor;
+
+        driverdata->hdpi = driverdata->physical_width ?
+            (((float) driverdata->width) * 25.4f / driverdata->physical_width) :
+            0.0f;
+        driverdata->vdpi = driverdata->physical_height ?
+            (((float) driverdata->height) * 25.4f / driverdata->physical_height) :
+            0.0f;
+        driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->width,
+                                                  driverdata->height,
+                                                  ((float) driverdata->physical_width) / 25.4f,
+                                                  ((float) driverdata->physical_height) / 25.4f);
     }
     mode.refresh_rate = driverdata->refresh / 1000; /* mHz to Hz */
     mode.driverdata = driverdata->output;
@@ -511,6 +539,24 @@ Wayland_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
     return 0;
 }
 
+static int
+Wayland_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi)
+{
+    SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *)sdl_display->driverdata;
+
+    if (ddpi) {
+        *ddpi = driverdata->ddpi;
+    }
+    if (hdpi) {
+        *hdpi = driverdata->hdpi;
+    }
+    if (vdpi) {
+        *vdpi = driverdata->vdpi;
+    }
+
+    return driverdata->ddpi != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
 void
 Wayland_VideoQuit(_THIS)
 {
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index 91dac3654..11f0e591d 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -94,6 +94,8 @@ typedef struct {
     struct wl_output *output;
     float scale_factor;
     int x, y, width, height, refresh, transform;
+    int physical_width, physical_height;
+    float ddpi, hdpi, vdpi;
     SDL_VideoDisplay placeholder;
     SDL_bool done;
 } SDL_WaylandOutputData;