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
This commit is contained in:
Eric Wasylishen 2023-01-11 19:45:01 -07:00 committed by Sam Lantinga
parent 6d11515873
commit 67c91353e0
11 changed files with 57 additions and 35 deletions

View file

@ -1261,7 +1261,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.

View file

@ -90,7 +90,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;
}

View file

@ -203,6 +203,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;
@ -280,7 +283,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) */
@ -288,11 +291,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();
@ -316,6 +319,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) {
@ -323,7 +329,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);
@ -2569,6 +2575,9 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window)
void *pixels = NULL;
int pitch = 0;
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
@ -2643,7 +2652,7 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window)
return window->surface;
}
return SDL_CreateSurfaceFrom(pixels, window->w, window->h, pitch, format);
return SDL_CreateSurfaceFrom(pixels, w, h, pitch, format);
}
SDL_Surface *SDL_GetWindowSurface(SDL_Window *window)
@ -2673,8 +2682,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);
}

View file

@ -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_CreateSurface(w, h, surface_format);
if (surface == NULL) {
return -1;

View file

@ -39,7 +39,7 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format
SDL_DestroySurface(surface);
/* Create a new one */
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &w, &h);
surface = SDL_CreateSurface(w, h, surface_format);
if (surface == NULL) {

View file

@ -69,7 +69,7 @@ SDL_FORCE_INLINE SDL_Surface *
CreateNewWindowFramebuffer(SDL_Window *window)
{
int w, h;
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &w, &h);
return SDL_CreateSurface(w, h, FRAMEBUFFER_FORMAT);
}

View file

@ -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_CreateSurface(w, h, surface_format);
if (surface == NULL) {
return -1;

View file

@ -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_CreateSurface(w, h, surface_format);
if (surface == NULL) {
return -1;

View file

@ -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) {

View file

@ -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);

View file

@ -55,6 +55,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);
@ -77,14 +80,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;
@ -108,7 +111,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);
@ -124,14 +127,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");
@ -147,6 +150,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) {
@ -167,11 +174,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,
@ -198,11 +205,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,