# HG changeset patch # User Edward Rudd # Date 1370362716 14400 # Node ID de459517506d4526a8d2dcfd77846193152aca1e # Parent 273094759fdd91afc8f89d2bc6d3dfa48b8fabdc Initial HIDPI support for SDL2. What works - creating a window with HIDPI enabled - creating a fullscreen-desktop window with HIDPI enabled - toggling between window and fullscreen-desktop What does not work - regular fullscreen mode fails to render things - when popping out of fullscreen (mode switch) to windowed rendering is "off" until you move the window. What is untested - anything to do with the SDL Rendering API. diff --git a/include/SDL_video.h b/include/SDL_video.h --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -107,7 +107,8 @@ SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */ SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), - SDL_WINDOW_FOREIGN = 0x00000800 /**< window not created by SDL */ + SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */ + SDL_WINDOW_HIDPI = 0x0000002000 /**< request hidpi mode if supported */ } SDL_WindowFlags; /** @@ -540,6 +541,20 @@ */ extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w, int *h); +/** + * \brief Gets the scale factor of the current window. + * + * \param scale_x Pointer to variable for storing the X scale, may be NULL + * \param scale_y Pointer to variable for storing the Y scale, may be NULL + * + * + * \note This will always return 1.0f/1.0f unless on a display that supports + * HiDPI Resolutions + * + * \sa SDL_WINDOW_HIDPI + */ +extern DECLSPEC void SDLCALL SDL_GetWindowScale(SDL_Window * window, + float *scale_x, float *scale_y); /** * \brief Set the minimum size of a window's client area. diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -368,6 +368,10 @@ state->window_flags |= SDL_WINDOW_INPUT_GRABBED; return 1; } + if (SDL_strcasecmp(argv[index], "--hidpi") == 0) { + state->window_flags |= SDL_WINDOW_HIDPI; + return 1; + } if (SDL_strcasecmp(argv[index], "--rate") == 0) { ++index; if (!argv[index]) { diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -184,6 +184,7 @@ void (*SetWindowIcon) (_THIS, SDL_Window * window, SDL_Surface * icon); void (*SetWindowPosition) (_THIS, SDL_Window * window); void (*SetWindowSize) (_THIS, SDL_Window * window); + void (*GetWindowScale) (_THIS, SDL_Window * window, float * sx, float * sy); void (*SetWindowMinimumSize) (_THIS, SDL_Window * window); void (*SetWindowMaximumSize) (_THIS, SDL_Window * window); void (*ShowWindow) (_THIS, SDL_Window * window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1152,7 +1152,7 @@ } #define CREATE_FLAGS \ - (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE) + (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDPI) static void SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags) @@ -1608,6 +1608,22 @@ } void +SDL_GetWindowScale(SDL_Window * window, float *scale_x, float *scale_y) +{ + float sx = 1.0f, sy = 1.0f; + CHECK_WINDOW_MAGIC(window, ); + if (_this->GetWindowScale) { + _this->GetWindowScale(_this, window, &sx, &sy); + } + if (scale_x) { + *scale_x = sx; + } + if (scale_y) { + *scale_y = sy; + } +} + +void SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h) { CHECK_WINDOW_MAGIC(window, ); diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -95,6 +95,7 @@ device->SetWindowIcon = Cocoa_SetWindowIcon; device->SetWindowPosition = Cocoa_SetWindowPosition; device->SetWindowSize = Cocoa_SetWindowSize; + device->GetWindowScale = Cocoa_GetWindowScale; device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize; device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize; device->ShowWindow = Cocoa_ShowWindow; diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -98,6 +98,7 @@ extern void Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); extern void Cocoa_SetWindowPosition(_THIS, SDL_Window * window); extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window); +extern void Cocoa_GetWindowScale(_THIS, SDL_Window * window, float * sx, float * sy); extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window); extern void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window); extern void Cocoa_ShowWindow(_THIS, SDL_Window * window); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -33,6 +33,12 @@ #include "SDL_cocoashape.h" #include "SDL_cocoamouse.h" +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 +@interface NSView (OpenGLRetinaAdditions) +- (NSRect)convertRectToBacking:(NSRect)aRect; +- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag; +@end +#endif static Uint32 s_moveHack; @@ -697,6 +703,15 @@ rect = [nswindow contentRectForFrameRect:[nswindow frame]]; NSView *contentView = [[SDLView alloc] initWithFrame:rect]; [nswindow setContentView: contentView]; + + // DPI is only valid for explicit OpenGL right now + if ( (window->flags & (SDL_WINDOW_OPENGL | SDL_WINDOW_HIDPI)) == (SDL_WINDOW_OPENGL | SDL_WINDOW_HIDPI) ) + { + if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) { + [contentView setWantsBestResolutionOpenGLSurface:YES]; + } + } + [contentView release]; [pool release]; @@ -805,6 +820,24 @@ } void +Cocoa_GetWindowScale(_THIS, SDL_Window * window, float * sx, float * sy) +{ + SDL_WindowData *windata = (SDL_WindowData *) window->driverdata; + NSWindow *nswindow = windata->nswindow; + + NSView *view = [nswindow contentView]; + if ((window->flags & SDL_WINDOW_HIDPI) && [view respondsToSelector:@selector(convertRectToBacking:)]) { + NSRect orig = [view bounds]; + NSRect rect = [view convertRectToBacking:orig]; + *sx = rect.size.width / orig.size.width; + *sy = rect.size.height / orig.size.height; + } else { + *sx = 1.0f; + *sy = 1.0f; + } +} + +void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/test/testgl2.c b/test/testgl2.c --- a/test/testgl2.c +++ b/test/testgl2.c @@ -180,6 +180,7 @@ SDL_Event event; Uint32 then, now, frames; int status; + float sx, sy; /* Initialize parameters */ fsaa = 0; @@ -249,8 +250,11 @@ } SDL_GetCurrentDisplayMode(0, &mode); + SDL_GetWindowScale(state->windows[0], &sx, &sy); printf("Screen BPP : %d\n", SDL_BITSPERPIXEL(mode.format)); printf("Swap Interval : %d\n", SDL_GL_GetSwapInterval()); + printf("Window Size : %d,%d\n", state->window_w, state->window_h); + printf("Back buffer : %d,%d\n", (int)(state->window_w * sx), (int)(state->window_h * sy)); printf("\n"); printf("Vendor : %s\n", glGetString(GL_VENDOR)); printf("Renderer : %s\n", glGetString(GL_RENDERER)); @@ -331,10 +335,17 @@ SDLTest_CommonEvent(state, &event, &done); } for (i = 0; i < state->num_windows; ++i) { + static int prev_w = 0, prev_h = 0; int w, h; + float sx, sy; SDL_GL_MakeCurrent(state->windows[i], context); SDL_GetWindowSize(state->windows[i], &w, &h); - glViewport(0, 0, w, h); + SDL_GetWindowScale(state->windows[i], &sx, &sy); + if (prev_h != (h * sy) || prev_w != (w * sx)) { + prev_h = h * sy; prev_w = w * sx; + printf("Changing resolution to (%d, %d) as scale (%f, %f)]\n", w, h, sx, sy); + } + glViewport(0, 0, w * sx, h * sy); Render(); SDL_GL_SwapWindow(state->windows[i]); }