Commit 76392f4fe1ac827b093907004c304fba90bb807c

Eric Wasylishen 2023-01-11T19:45:01

Handle DPI scaling in SDL_GetWindowSurface Fixes DPI awareness of testdrawchessboard (previously, the surface was being created in points instead of pixels, resulting in the demo app only drawing in a corner of the screen on High-DPI displays) *_CreateWindowFramebuffer()/*_UpdateWindowFramebuffer(): are updated to use SDL_GetWindowSizeInPixels instead of SDL_GetWindowSize() or window->w/window->h. Most of the _CreateWindowFramebuffer backends are untested except for Windows. Fixes #7047 (cherry picked from commit 67c91353e01f6f2c0cc80c17eeddbad6def7cb01)

diff --git a/include/SDL_video.h b/include/SDL_video.h
index 99637f7..c8b2d7a 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -1342,7 +1342,7 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window);
  *
  * \param window the window to update
  * \param rects an array of SDL_Rect structures representing areas of the
- *              surface to copy
+ *              surface to copy, in pixels
  * \param numrects the number of rectangles
  * \returns 0 on success or a negative error code on failure; call
  *          SDL_GetError() for more information.
diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index 3196844..edf4923 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -91,7 +91,7 @@ static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
     }
 
     if (renderer->window) {
-        SDL_GetWindowSize(renderer->window, w, h);
+        SDL_GetWindowSizeInPixels(renderer->window, w, h);
         return 0;
     }
 
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index dbd4740..84dfcc1 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -219,6 +219,9 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
     SDL_RendererInfo info;
     SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
     int i;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     if (data == NULL) {
         SDL_Renderer *renderer = NULL;
@@ -301,7 +304,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
 
     data->texture = SDL_CreateTexture(data->renderer, *format,
                                       SDL_TEXTUREACCESS_STREAMING,
-                                      window->w, window->h);
+                                      w, h);
     if (!data->texture) {
         /* codechecker_false_positive [Malloc] Static analyzer doesn't realize allocated `data` is saved to SDL_WINDOWTEXTUREDATA and not leaked here. */
         return -1; /* NOLINT(clang-analyzer-unix.Malloc) */
@@ -309,11 +312,11 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
 
     /* Create framebuffer data */
     data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
-    data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
+    data->pitch = (((w * data->bytes_per_pixel) + 3) & ~3);
 
     {
         /* Make static analysis happy about potential SDL_malloc(0) calls. */
-        const size_t allocsize = (size_t)window->h * data->pitch;
+        const size_t allocsize = (size_t)h * data->pitch;
         data->pixels = SDL_malloc((allocsize > 0) ? allocsize : 1);
         if (!data->pixels) {
             return SDL_OutOfMemory();
@@ -337,6 +340,9 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, 
     SDL_WindowTextureData *data;
     SDL_Rect rect;
     void *src;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
     if (data == NULL || !data->texture) {
@@ -344,7 +350,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window, 
     }
 
     /* Update a single rect that contains subrects for best DMA performance */
-    if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
+    if (SDL_GetSpanEnclosingRect(w, h, numrects, rects, &rect)) {
         src = (void *)((Uint8 *)data->pixels +
                        rect.y * data->pitch +
                        rect.x * data->bytes_per_pixel);
@@ -2584,6 +2590,9 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window)
     int bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
     SDL_bool created_framebuffer = SDL_FALSE;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     /* This will switch the video backend from using a software surface to
        using a GPU texture through the 2D render API, if we think this would
@@ -2662,7 +2671,7 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window)
         return NULL;
     }
 
-    return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
+    return SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
 }
 
 SDL_bool SDL_HasWindowSurface(SDL_Window *window)
@@ -2695,8 +2704,8 @@ int SDL_UpdateWindowSurface(SDL_Window *window)
 
     full_rect.x = 0;
     full_rect.y = 0;
-    full_rect.w = window->w;
-    full_rect.h = window->h;
+    SDL_GetWindowSizeInPixels(window, &full_rect.w, &full_rect.h);
+
     return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
 }
 
diff --git a/src/video/dummy/SDL_nullframebuffer.c b/src/video/dummy/SDL_nullframebuffer.c
index 55e3962..be10dd1 100644
--- a/src/video/dummy/SDL_nullframebuffer.c
+++ b/src/video/dummy/SDL_nullframebuffer.c
@@ -37,7 +37,7 @@ int SDL_DUMMY_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
     SDL_DUMMY_DestroyWindowFramebuffer(_this, window);
 
     /* Create a new one */
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
     surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format);
     if (surface == NULL) {
         return -1;
diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.c b/src/video/emscripten/SDL_emscriptenframebuffer.c
index 80f1534..6226198 100644
--- a/src/video/emscripten/SDL_emscriptenframebuffer.c
+++ b/src/video/emscripten/SDL_emscriptenframebuffer.c
@@ -43,7 +43,7 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format
 
     /* Create a new one */
     SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
     if (surface == NULL) {
diff --git a/src/video/n3ds/SDL_n3dsframebuffer.c b/src/video/n3ds/SDL_n3dsframebuffer.c
index d0e52d6..601e8bc 100644
--- a/src/video/n3ds/SDL_n3dsframebuffer.c
+++ b/src/video/n3ds/SDL_n3dsframebuffer.c
@@ -71,7 +71,7 @@ CreateNewWindowFramebuffer(SDL_Window *window)
     int w, h, bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
     SDL_PixelFormatEnumToMasks(FRAMEBUFFER_FORMAT, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
     return SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
 }
 
diff --git a/src/video/ngage/SDL_ngageframebuffer.cpp b/src/video/ngage/SDL_ngageframebuffer.cpp
index a27a48f..20b1857 100644
--- a/src/video/ngage/SDL_ngageframebuffer.cpp
+++ b/src/video/ngage/SDL_ngageframebuffer.cpp
@@ -55,7 +55,7 @@ int SDL_NGAGE_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
     SDL_NGAGE_DestroyWindowFramebuffer(_this, window);
 
     /* Create a new one */
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
     surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format);
     if (surface == NULL) {
         return -1;
diff --git a/src/video/offscreen/SDL_offscreenframebuffer.c b/src/video/offscreen/SDL_offscreenframebuffer.c
index d71f042..4e27c72 100644
--- a/src/video/offscreen/SDL_offscreenframebuffer.c
+++ b/src/video/offscreen/SDL_offscreenframebuffer.c
@@ -37,7 +37,7 @@ int SDL_OFFSCREEN_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *for
     SDL_OFFSCREEN_DestroyWindowFramebuffer(_this, window);
 
     /* Create a new one */
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetWindowSizeInPixels(window, &w, &h);
     surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format);
     if (surface == NULL) {
         return -1;
diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c
index 2b08c92..36ce340 100644
--- a/src/video/riscos/SDL_riscosframebuffer.c
+++ b/src/video/riscos/SDL_riscosframebuffer.c
@@ -39,6 +39,9 @@ int RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, vo
     _kernel_swi_regs regs;
     SDL_DisplayMode mode;
     int size;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     /* Free the old framebuffer surface */
     RISCOS_DestroyWindowFramebuffer(_this, window);
@@ -54,10 +57,10 @@ int RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, vo
     }
 
     /* Calculate pitch */
-    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+    *pitch = (((w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
 
     /* Allocate the sprite area */
-    size = sizeof(sprite_area) + sizeof(sprite_header) + ((*pitch) * window->h);
+    size = sizeof(sprite_area) + sizeof(sprite_header) + ((*pitch) * h);
     driverdata->fb_area = SDL_malloc(size);
     if (!driverdata->fb_area) {
         return SDL_OutOfMemory();
@@ -73,8 +76,8 @@ int RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, vo
     regs.r[1] = (int)driverdata->fb_area;
     regs.r[2] = (int)sprite_name;
     regs.r[3] = 0;
-    regs.r[4] = window->w;
-    regs.r[5] = window->h;
+    regs.r[4] = w;
+    regs.r[5] = h;
     regs.r[6] = sprite_mode;
     error = _kernel_swi(OS_SpriteOp, &regs, &regs);
     if (error != NULL) {
diff --git a/src/video/windows/SDL_windowsframebuffer.c b/src/video/windows/SDL_windowsframebuffer.c
index f251a7b..8248352 100644
--- a/src/video/windows/SDL_windowsframebuffer.c
+++ b/src/video/windows/SDL_windowsframebuffer.c
@@ -31,6 +31,9 @@ int WIN_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void 
     size_t size;
     LPBITMAPINFO info;
     HBITMAP hbm;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     /* Free the old framebuffer surface */
     if (data->mdc) {
@@ -78,10 +81,10 @@ int WIN_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void 
     }
 
     /* Fill in the size information */
-    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
-    info->bmiHeader.biWidth = window->w;
-    info->bmiHeader.biHeight = -window->h; /* negative for topdown bitmap */
-    info->bmiHeader.biSizeImage = (DWORD)window->h * (*pitch);
+    *pitch = (((w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+    info->bmiHeader.biWidth = w;
+    info->bmiHeader.biHeight = -h; /* negative for topdown bitmap */
+    info->bmiHeader.biSizeImage = (DWORD)h * (*pitch);
 
     data->mdc = CreateCompatibleDC(data->hdc);
     data->hbm = CreateDIBSection(data->hdc, info, DIB_RGB_COLORS, pixels, NULL, 0);
diff --git a/src/video/x11/SDL_x11framebuffer.c b/src/video/x11/SDL_x11framebuffer.c
index f9ce74a..403dbd3 100644
--- a/src/video/x11/SDL_x11framebuffer.c
+++ b/src/video/x11/SDL_x11framebuffer.c
@@ -54,6 +54,9 @@ int X11_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
     Display *display = data->videodata->display;
     XGCValues gcv;
     XVisualInfo vinfo;
+    int w, h;
+
+    SDL_GetWindowSizeInPixels(window, &w, &h);
 
     /* Free the old framebuffer surface */
     X11_DestroyWindowFramebuffer(_this, window);
@@ -76,14 +79,14 @@ int X11_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
     }
 
     /* Calculate pitch */
-    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+    *pitch = (((w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
 
     /* Create the actual image */
 #ifndef NO_SHARED_MEMORY
     if (have_mitshm(display)) {
         XShmSegmentInfo *shminfo = &data->shminfo;
 
-        shminfo->shmid = shmget(IPC_PRIVATE, (size_t)window->h * (*pitch), IPC_CREAT | 0777);
+        shminfo->shmid = shmget(IPC_PRIVATE, (size_t)h * (*pitch), IPC_CREAT | 0777);
         if (shminfo->shmid >= 0) {
             shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
             shminfo->readOnly = False;
@@ -107,7 +110,7 @@ int X11_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
             data->ximage = X11_XShmCreateImage(display, data->visual,
                                                vinfo.depth, ZPixmap,
                                                shminfo->shmaddr, shminfo,
-                                               window->w, window->h);
+                                               w, h);
             if (!data->ximage) {
                 X11_XShmDetach(display, shminfo);
                 X11_XSync(display, False);
@@ -123,14 +126,14 @@ int X11_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format,
     }
 #endif /* not NO_SHARED_MEMORY */
 
-    *pixels = SDL_malloc((size_t)window->h * (*pitch));
+    *pixels = SDL_malloc((size_t)h * (*pitch));
     if (*pixels == NULL) {
         return SDL_OutOfMemory();
     }
 
     data->ximage = X11_XCreateImage(display, data->visual,
                                     vinfo.depth, ZPixmap, 0, (char *)(*pixels),
-                                    window->w, window->h, 32, 0);
+                                    w, h, 32, 0);
     if (!data->ximage) {
         SDL_free(*pixels);
         return SDL_SetError("Couldn't create XImage");
@@ -146,6 +149,10 @@ int X11_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects
     Display *display = data->videodata->display;
     int i;
     int x, y, w, h;
+    int window_w, window_h;
+
+    SDL_GetWindowSizeInPixels(window, &window_w, &window_h);
+
 #ifndef NO_SHARED_MEMORY
     if (data->use_mitshm) {
         for (i = 0; i < numrects; ++i) {
@@ -166,11 +173,11 @@ int X11_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects
                 y += h;
                 h += rects[i].y;
             }
-            if (x + w > window->w) {
-                w = window->w - x;
+            if (x + w > window_w) {
+                w = window_w - x;
             }
-            if (y + h > window->h) {
-                h = window->h - y;
+            if (y + h > window_h) {
+                h = window_h - y;
             }
 
             X11_XShmPutImage(display, data->xwindow, data->gc, data->ximage,
@@ -197,11 +204,11 @@ int X11_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects
                 y += h;
                 h += rects[i].y;
             }
-            if (x + w > window->w) {
-                w = window->w - x;
+            if (x + w > window_w) {
+                w = window_w - x;
             }
-            if (y + h > window->h) {
-                h = window->h - y;
+            if (y + h > window_h) {
+                h = window_h - y;
             }
 
             X11_XPutImage(display, data->xwindow, data->gc, data->ximage,