Skip to content

Commit

Permalink
Changed the way retina resolutions are handled in iOS.
Browse files Browse the repository at this point in the history
Previously, SDL would always expose display modes and window dimensions in terms of pixels, and would add an extra 'fake' display mode on retina screens which would contain the non-retina resolution. Calling SDL_CreateWindow with the dimensions of that fake display mode would not work.

Now, SDL only exposes display modes and window dimensions in terms of points rather than pixels. If the SDL_WINDOW_ALLOW_HIGHDPI flag is passed into SDL_CreateWindow, then any OpenGL contexts created from that window will be sized in pixels rather than points (retrievable with SDL_GL_GetDrawableSize.) Window dimensions and mouse coordinates are still in terms of points rather than pixels even with that flag.

This matches the behavior of SDL in OS X more closely, and lets users choose whether to make use of retina displays and lets them handle it properly.
  • Loading branch information
slime73 committed Jul 15, 2014
1 parent 734b523 commit 3672409
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 82 deletions.
2 changes: 0 additions & 2 deletions src/video/uikit/SDL_uikitmodes.h
Expand Up @@ -28,13 +28,11 @@
typedef struct
{
UIScreen *uiscreen;
CGFloat scale;
} SDL_DisplayData;

typedef struct
{
UIScreenMode *uiscreenmode;
CGFloat scale;
} SDL_DisplayModeData;

extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
Expand Down
50 changes: 16 additions & 34 deletions src/video/uikit/SDL_uikitmodes.m
Expand Up @@ -28,7 +28,7 @@

static int
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
UIScreenMode * uiscreenmode, CGFloat scale)
UIScreenMode * uiscreenmode)
{
SDL_DisplayModeData *data = NULL;

Expand All @@ -41,8 +41,6 @@

data->uiscreenmode = uiscreenmode;
[data->uiscreenmode retain];

data->scale = scale;
}

mode->driverdata = data;
Expand All @@ -63,14 +61,14 @@

static int
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
UIScreenMode * uiscreenmode, CGFloat scale)
UIScreenMode * uiscreenmode)
{
SDL_DisplayMode mode;
SDL_zero(mode);

mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.refresh_rate = 0;
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}

Expand All @@ -85,16 +83,16 @@
}

static int
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale,
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h,
UIScreenMode * uiscreenmode, SDL_bool addRotation)
{
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) {
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode) < 0) {
return -1;
}

if (addRotation) {
/* Add the rotated version */
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) {
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode) < 0) {
return -1;
}
}
Expand All @@ -114,24 +112,16 @@
size.height = height;
}

/* When dealing with UIKit all coordinates are specified in terms of
* what Apple refers to as points. [UIScreen scale] indicates the
* relationship between points and pixels. Since SDL has no notion
* of points, we must compensate in all cases where dealing with such
* units.
*/
CGFloat scale = [uiscreen scale];

SDL_VideoDisplay display;
SDL_DisplayMode mode;
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.w = (int)(size.width * scale);
mode.h = (int)(size.height * scale);
mode.w = (int) size.width;
mode.h = (int) size.height;

UIScreenMode * uiscreenmode = [uiscreen currentMode];
UIScreenMode *uiscreenmode = [uiscreen currentMode];

if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}

Expand All @@ -148,7 +138,6 @@

[uiscreen retain];
data->uiscreen = uiscreen;
data->scale = scale;

display.driverdata = data;
SDL_AddVideoDisplay(&display);
Expand Down Expand Up @@ -186,11 +175,14 @@

SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen);
SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]);
CGFloat scale = data->uiscreen.scale;

for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
/* The size of a UIScreenMode is in pixels, but we deal exclusively in
* points (except in SDL_GL_GetDrawableSize.) */
CGSize size = [uimode size];
int w = (int)size.width;
int h = (int)size.height;
int w = (int)(size.width / scale);
int h = (int)(size.height / scale);

/* Make sure the width/height are oriented correctly */
if (isLandscape != (w > h)) {
Expand All @@ -200,17 +192,7 @@
}

/* Add the native screen resolution. */
UIKit_AddDisplayMode(display, w, h, data->scale, uimode, addRotation);

if (data->scale != 1.0f) {
/* Add the native screen resolution divided by its scale.
* This is so devices capable of e.g. 640x960 also advertise 320x480.
*/
UIKit_AddDisplayMode(display,
(int)(size.width / data->scale),
(int)(size.height / data->scale),
1.0f, uimode, addRotation);
}
UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/video/uikit/SDL_uikitopengles.h
Expand Up @@ -25,6 +25,8 @@

extern int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window,
SDL_GLContext context);
extern void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window,
int * w, int * h);
extern void UIKit_GL_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window);
extern void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context);
Expand Down
42 changes: 32 additions & 10 deletions src/video/uikit/SDL_uikitopengles.m
Expand Up @@ -49,7 +49,8 @@
/*
note that SDL_GL_Delete context makes it current without passing the window
*/
int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
int
UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
if (context) {
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
Expand All @@ -62,6 +63,19 @@ int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
return 0;
}

void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
{
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;

if (w) {
*w = data->view.backingWidth;
}
if (h) {
*h = data->view.backingHeight;
}
}


int
UIKit_GL_LoadLibrary(_THIS, const char *path)
{
Expand Down Expand Up @@ -96,15 +110,22 @@ void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
*/
}

SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
SDL_GLContext
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
{
SDL_uikitopenglview *view;
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *displaydata = display->driverdata;
SDL_DisplayModeData *displaymodedata = display->current_mode.driverdata;
UIWindow *uiwindow = data->uiwindow;
EAGLSharegroup *share_group = nil;
CGFloat scale = 1.0;

if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
/* Set the scale to the natural scale factor of the screen - the backing
dimensions of the OpenGL view will match the pixel dimensions of the
screen rather than the dimensions in points.
*/
scale = [uiwindow screen].scale;
}

if (_this->gl_config.share_with_current_context) {
SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
Expand All @@ -114,12 +135,12 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
/* construct our view, passing in SDL's OpenGL configuration data */
CGRect frame;
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
frame = [displaydata->uiscreen bounds];
frame = [[uiwindow screen] bounds];
} else {
frame = [displaydata->uiscreen applicationFrame];
frame = [[uiwindow screen] applicationFrame];
}
view = [[SDL_uikitopenglview alloc] initWithFrame: frame
scale: displaymodedata->scale
scale: scale
retainBacking: _this->gl_config.retained_backing
rBits: _this->gl_config.red_size
gBits: _this->gl_config.green_size
Expand Down Expand Up @@ -152,15 +173,16 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
}

/* Make this window the current mouse focus for touch input */
if (displaydata->uiscreen == [UIScreen mainScreen]) {
if ([uiwindow screen] == [UIScreen mainScreen]) {
SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window);
}

return view;
}

void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
void
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
{
/* the delegate has retained the view, this will release him */
SDL_uikitopenglview *view = (SDL_uikitopenglview *)context;
Expand Down
4 changes: 4 additions & 0 deletions src/video/uikit/SDL_uikitopenglview.h
Expand Up @@ -55,6 +55,10 @@

@property (nonatomic, retain, readonly) EAGLContext *context;

/* The width and height of the drawable in pixels (as opposed to points.) */
@property (nonatomic, readonly) int backingWidth;
@property (nonatomic, readonly) int backingHeight;

- (void)swapBuffers;
- (void)setCurrentContext;

Expand Down
7 changes: 6 additions & 1 deletion src/video/uikit/SDL_uikitopenglview.m
Expand Up @@ -32,6 +32,9 @@ @implementation SDL_uikitopenglview

@synthesize context;

@synthesize backingWidth = backingWidth;
@synthesize backingHeight = backingHeight;

+ (Class)layerClass
{
return [CAEAGLLayer class];
Expand Down Expand Up @@ -74,7 +77,9 @@ - (id)initWithFrame:(CGRect)frame

eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
[NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking,
colorFormat, kEAGLDrawablePropertyColorFormat,
nil];

context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
if (!context || ![EAGLContext setCurrentContext:context]) {
Expand Down
7 changes: 4 additions & 3 deletions src/video/uikit/SDL_uikitvideo.m
Expand Up @@ -93,12 +93,13 @@ static void UIKit_DeleteDevice(SDL_VideoDevice * device)
#endif

/* OpenGL (ES) functions */
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
device->GL_SwapWindow = UIKit_GL_SwapWindow;
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
device->GL_SwapWindow = UIKit_GL_SwapWindow;
device->GL_CreateContext = UIKit_GL_CreateContext;
device->GL_DeleteContext = UIKit_GL_DeleteContext;
device->GL_GetProcAddress = UIKit_GL_GetProcAddress;
device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
device->free = UIKit_DeleteDevice;

device->gl_config.accelerated = 1;
Expand Down
14 changes: 1 addition & 13 deletions src/video/uikit/SDL_uikitview.m
Expand Up @@ -65,19 +65,12 @@ - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
{
CGPoint point = [touch locationInView: self];

/* Get the display scale and apply that to the input coordinates */
SDL_Window *window = viewcontroller.window;
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;

if (normalize) {
CGRect bounds = [self bounds];
point.x /= bounds.size.width;
point.y /= bounds.size.height;
} else {
point.x *= displaymodedata->scale;
point.y *= displaymodedata->scale;
}

return point;
}

Expand Down Expand Up @@ -360,7 +353,6 @@ void _uikit_keyboard_update() {
int height = view.keyboardHeight;
int offsetx = 0;
int offsety = 0;
float scale = [UIScreen mainScreen].scale;
if (height) {
int sw,sh;
SDL_GetWindowSize(window,&sw,&sh);
Expand All @@ -382,9 +374,6 @@ void _uikit_keyboard_update() {
offsety = -offsety;
}

offsetx /= scale;
offsety /= scale;

view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
}

Expand Down Expand Up @@ -412,7 +401,6 @@ void _uikit_keyboard_init() {
if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
height = keyboardSize.width;
}
height *= [UIScreen mainScreen].scale;
_uikit_keyboard_set_height(height);
}
];
Expand Down
2 changes: 1 addition & 1 deletion src/video/uikit/SDL_uikitviewcontroller.h
Expand Up @@ -28,7 +28,7 @@
SDL_Window *window;
}

@property (readwrite) SDL_Window *window;
@property (nonatomic, readwrite) SDL_Window *window;

- (id)initWithSDLWindow:(SDL_Window *)_window;
- (void)loadView;
Expand Down
12 changes: 4 additions & 8 deletions src/video/uikit/SDL_uikitviewcontroller.m
Expand Up @@ -56,15 +56,11 @@ - (void)loadView

- (void)viewDidLayoutSubviews
{
if (self->window->flags & SDL_WINDOW_RESIZABLE) {
SDL_WindowData *data = self->window->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(self->window);
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
if (window->flags & SDL_WINDOW_RESIZABLE) {
SDL_WindowData *data = window->driverdata;
const CGSize size = data->view.bounds.size;
int w, h;

w = (int)(size.width * displaymodedata->scale);
h = (int)(size.height * displaymodedata->scale);
int w = (int) size.width;
int h = (int) size.height;

SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h);
}
Expand Down

0 comments on commit 3672409

Please sign in to comment.