Work-in-progress patch to add OSX retina support to SDL 1.2.15
diff -r 4488c8602961 Xcode/SDL/SDL.xcodeproj/project.pbxproj | |
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj Tue Apr 09 07:45:32 2013 +1000 | |
@@ -1742,6 +1742,7 @@ | |
OTHER_CFLAGS_ppc = ""; | |
OTHER_LDFLAGS_ppc = "-prebind -seg1addr 0x30000000"; | |
PRODUCT_NAME = SDL; | |
+ SDKROOT = macosx10.7; | |
WRAPPER_EXTENSION = framework; | |
}; | |
name = Release; | |
@@ -1834,6 +1835,7 @@ | |
OTHER_CFLAGS_i386 = ""; | |
OTHER_CFLAGS_ppc = ""; | |
PRODUCT_NAME = SDL; | |
+ SDKROOT = macosx10.7; | |
WRAPPER_EXTENSION = framework; | |
}; | |
name = Debug; | |
diff -r 4488c8602961 include/SDL_video.h | |
--- a/include/SDL_video.h Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/include/SDL_video.h Tue Apr 09 07:45:32 2013 +1000 | |
@@ -143,6 +143,7 @@ | |
#define SDL_OPENGLBLIT 0x0000000A /**< Create an OpenGL rendering context and use it for blitting */ | |
#define SDL_RESIZABLE 0x00000010 /**< This video mode may be resized */ | |
#define SDL_NOFRAME 0x00000020 /**< No window caption or edge frame */ | |
+#define SDL_HIGHDENSITY 0x00000008 /**< This video mode is high-density (i.e. Retina displays -- this flag currently only implemented on OSX TODO: NOT CURRENTLY FULLY WORKING) */ | |
/*@}*/ | |
/** Used internally (read-only) */ | |
@@ -314,11 +315,11 @@ | |
/** | |
* Return a pointer to an array of available screen dimensions for the | |
- * given format and video flags, sorted largest to smallest. Returns | |
- * NULL if there are no dimensions available for a particular format, | |
+ * given format and video flags, sorted largest to smallest. Returns | |
+ * NULL if there are no dimensions available for a particular format, | |
* or (SDL_Rect **)-1 if any dimension is okay for the given format. | |
* | |
- * If 'format' is NULL, the mode list will be for the format given | |
+ * If 'format' is NULL, the mode list will be for the format given | |
* by SDL_GetVideoInfo()->vfmt | |
*/ | |
extern DECLSPEC SDL_Rect ** SDLCALL SDL_ListModes(SDL_PixelFormat *format, Uint32 flags); | |
@@ -347,21 +348,21 @@ | |
* Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all | |
* of the colors exactly the way they are requested, and you should look | |
* at the video surface structure to determine the actual palette. | |
- * If SDL cannot guarantee that the colors you request can be set, | |
+ * If SDL cannot guarantee that the colors you request can be set, | |
* i.e. if the colormap is shared, then the video surface may be created | |
* under emulation in system memory, overriding the SDL_HWSURFACE flag. | |
* | |
* If SDL_FULLSCREEN is set in 'flags', the SDL library will try to set | |
* a fullscreen video mode. The default is to create a windowed mode | |
* if the current graphics system has a window manager. | |
- * If the SDL library is able to set a fullscreen video mode, this flag | |
+ * If the SDL library is able to set a fullscreen video mode, this flag | |
* will be set in the surface that is returned. | |
* | |
* If SDL_DOUBLEBUF is set in 'flags', the SDL library will try to set up | |
- * two surfaces in video memory and swap between them when you call | |
+ * two surfaces in video memory and swap between them when you call | |
* SDL_Flip(). This is usually slower than the normal single-buffering | |
- * scheme, but prevents "tearing" artifacts caused by modifying video | |
- * memory while the monitor is refreshing. It should only be used by | |
+ * scheme, but prevents "tearing" artifacts caused by modifying video | |
+ * memory while the monitor is refreshing. It should only be used by | |
* applications that redraw the entire screen on every update. | |
* | |
* If SDL_RESIZABLE is set in 'flags', the SDL library will allow the | |
@@ -416,7 +417,7 @@ | |
/** | |
* Set the gamma correction for each of the color channels. | |
* The gamma values range (approximately) between 0.1 and 10.0 | |
- * | |
+ * | |
* If this function isn't supported directly by the hardware, it will | |
* be emulated using gamma ramps, if available. If successful, this | |
* function returns 0, otherwise it returns -1. | |
@@ -429,7 +430,7 @@ | |
* representing a mapping between the input and output for that channel. | |
* The input is the index into the array, and the output is the 16-bit | |
* gamma value at that index, scaled to the output color precision. | |
- * | |
+ * | |
* You may pass NULL for any of the channels to leave it unchanged. | |
* If the call succeeds, it will return 0. If the display driver or | |
* hardware does not support gamma translation, or otherwise fails, | |
@@ -439,7 +440,7 @@ | |
/** | |
* Retrieve the current values of the gamma translation tables. | |
- * | |
+ * | |
* You must pass in valid pointers to arrays of 256 16-bit quantities. | |
* Any of the pointers may be NULL to ignore that channel. | |
* If the call succeeds, it will return 0. If the display driver or | |
@@ -457,13 +458,13 @@ | |
* determine the actual color palette. | |
* | |
* When 'surface' is the surface associated with the current display, the | |
- * display colormap will be updated with the requested colors. If | |
+ * display colormap will be updated with the requested colors. If | |
* SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors() | |
* will always return 1, and the palette is guaranteed to be set the way | |
* you desire, even if the window colormap has to be warped or run under | |
* emulation. | |
*/ | |
-extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface *surface, | |
+extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface *surface, | |
SDL_Color *colors, int firstcolor, int ncolors); | |
/** | |
@@ -537,7 +538,7 @@ | |
* two surfaces in video memory, SDL will try to place the surface in | |
* video memory. If this isn't possible or if there is no hardware | |
* acceleration available, the surface will be placed in system memory. | |
- * SDL_SRCALPHA means that the surface will be used for alpha blits and | |
+ * SDL_SRCALPHA means that the surface will be used for alpha blits and | |
* if the hardware supports hardware acceleration of alpha blits between | |
* two surfaces in video memory, to place the surface in video memory | |
* if possible, otherwise it will be placed in system memory. | |
@@ -551,7 +552,7 @@ | |
* the SDL_HWSURFACE flag set, and will be created in system memory instead. | |
*/ | |
extern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurface | |
- (Uint32 flags, int width, int height, int depth, | |
+ (Uint32 flags, int width, int height, int depth, | |
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); | |
/** @sa SDL_CreateRGBSurface */ | |
extern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, | |
@@ -562,8 +563,8 @@ | |
/** | |
* SDL_LockSurface() sets up a surface for directly accessing the pixels. | |
* Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write | |
- * to and read from 'surface->pixels', using the pixel format stored in | |
- * 'surface->format'. Once you are done accessing the surface, you should | |
+ * to and read from 'surface->pixels', using the pixel format stored in | |
+ * 'surface->format'. Once you are done accessing the surface, you should | |
* use SDL_UnlockSurface() to release it. | |
* | |
* Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates | |
@@ -571,7 +572,7 @@ | |
* pixel format of the surface will not change. In particular, if the | |
* SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you | |
* will not need to lock the display surface before accessing it. | |
- * | |
+ * | |
* No operating system or library calls should be made between lock/unlock | |
* pairs, as critical system locks may be held during this time. | |
* | |
@@ -605,7 +606,7 @@ | |
/** | |
* Sets the color key (transparent pixel) in a blittable surface. | |
- * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), | |
+ * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), | |
* 'key' will be the transparent pixel in the source image of a blit. | |
* SDL_RLEACCEL requests RLE acceleration for the surface if present, | |
* and removes RLE acceleration if absent. | |
@@ -654,11 +655,11 @@ | |
extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect); | |
/** | |
- * Creates a new surface of the specified format, and then copies and maps | |
- * the given surface to it so the blit of the converted surface will be as | |
+ * Creates a new surface of the specified format, and then copies and maps | |
+ * the given surface to it so the blit of the converted surface will be as | |
* fast as possible. If this function fails, it returns NULL. | |
* | |
- * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those | |
+ * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those | |
* semantics. You can also pass SDL_RLEACCEL in the flags parameter and | |
* SDL will try to RLE accelerate colorkey and alpha blits in the resulting | |
* surface. | |
@@ -690,7 +691,7 @@ | |
* if SDL_SRCCOLORKEY set, only copy the pixels matching the | |
* RGB values of the source colour key, ignoring alpha in the | |
* comparison. | |
- * | |
+ * | |
* RGB->RGBA: | |
* SDL_SRCALPHA set: | |
* alpha-blend (using the source per-surface alpha value); | |
@@ -700,7 +701,7 @@ | |
* both: | |
* if SDL_SRCCOLORKEY set, only copy the pixels matching the | |
* source colour key. | |
- * | |
+ * | |
* RGBA->RGBA: | |
* SDL_SRCALPHA set: | |
* alpha-blend (using the source alpha channel) the RGB values; | |
@@ -711,8 +712,8 @@ | |
* if SDL_SRCCOLORKEY set, only copy the pixels matching the | |
* RGB values of the source colour key, ignoring alpha in the | |
* comparison. | |
- * | |
- * RGB->RGB: | |
+ * | |
+ * RGB->RGB: | |
* SDL_SRCALPHA set: | |
* alpha-blend (using the source per-surface alpha value). | |
* SDL_SRCALPHA not set: | |
@@ -722,7 +723,7 @@ | |
* source colour key. | |
* | |
* If either of the surfaces were in video memory, and the blit returns -2, | |
- * the video memory was lost, so it should be reloaded with artwork and | |
+ * the video memory was lost, so it should be reloaded with artwork and | |
* re-blitted: | |
* @code | |
* while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) { | |
@@ -760,7 +761,7 @@ | |
* The given rectangle is clipped to the destination surface clip area | |
* and the final fill rectangle is saved in the passed in pointer. | |
* If 'dstrect' is NULL, the whole surface will be filled with 'color' | |
- * The color should be a pixel of the format used by the surface, and | |
+ * The color should be a pixel of the format used by the surface, and | |
* can be generated by the SDL_MapRGB() function. | |
* This function returns 0 on success, or -1 on error. | |
*/ | |
@@ -813,7 +814,7 @@ | |
/** Blit a video overlay to the display surface. | |
* The contents of the video surface underneath the blit destination are | |
- * not defined. | |
+ * not defined. | |
* The width and height of the destination rectangle may be different from | |
* that of the overlay, but currently only 2x scaling is supported. | |
*/ | |
@@ -908,7 +909,7 @@ | |
* If the display surface does not require locking before accessing | |
* the pixel information, then the memory pointers will not change. | |
* | |
- * If this function was able to toggle fullscreen mode (change from | |
+ * If this function was able to toggle fullscreen mode (change from | |
* running in a window to fullscreen, or vice-versa), it will return 1. | |
* If it is not implemented, or fails, it returns 0. | |
* | |
@@ -941,7 +942,7 @@ | |
/** @internal Not in public API at the moment - do not use! */ | |
extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, | |
SDL_Surface *dst, SDL_Rect *dstrect); | |
- | |
+ | |
/* Ends C function definitions when using C++ */ | |
#ifdef __cplusplus | |
} | |
diff -r 4488c8602961 src/video/quartz/SDL_QuartzEvents.m | |
--- a/src/video/quartz/SDL_QuartzEvents.m Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/src/video/quartz/SDL_QuartzEvents.m Tue Apr 09 07:45:32 2013 +1000 | |
@@ -700,6 +700,9 @@ | |
if (qz_window) | |
QZ_PrivateGlobalToLocal (this, p); | |
QZ_PrivateCocoaToSDL (this, p); | |
+ // now convert from points to pixels | |
+ *p = [ window_view convertPointToBacking:*p ]; | |
+ | |
} | |
void QZ_DoActivate (_THIS) { | |
diff -r 4488c8602961 src/video/quartz/SDL_QuartzVideo.m | |
--- a/src/video/quartz/SDL_QuartzVideo.m Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/src/video/quartz/SDL_QuartzVideo.m Tue Apr 09 07:45:32 2013 +1000 | |
@@ -49,7 +49,7 @@ | |
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__) /* Fixed in Snow Leopard */ | |
/* | |
- Add methods to get at private members of NSScreen. | |
+ Add methods to get at private members of NSScreen. | |
Since there is a bug in Apple's screen switching code | |
that does not update this variable when switching | |
to fullscreen, we'll set it manually (but only for the | |
@@ -384,7 +384,7 @@ | |
/* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ | |
QZ_RegisterForSleepNotifications (this); | |
- | |
+ | |
/* Fill in some window manager capabilities */ | |
this->info.wm_available = 1; | |
@@ -435,6 +435,25 @@ | |
QZ_GetModeInfo(this, onemode, &width, &height, &bpp); | |
+ // if we're on a retina device but NOT using retina mode, | |
+ // then we need to convert the width and height (which are expressed in retina pixels) | |
+ // into non-retina pixels (i.e.: "points"). | |
+ | |
+ //if ( 0 == (flags & SDL_HIGHDENSITY) ) | |
+ { | |
+ /*CGPoint point; | |
+ point.x = width; | |
+ point.y = height; | |
+ CGContextRef context = CGDisplayGetDrawingContext(display_id); | |
+ point = CGContextConvertPointToUserSpace(context, point); | |
+ width = point.x; | |
+ height = point.y;*/ | |
+ | |
+ /*float scaleFactor = [[ NSScreen mainScreen ] backingScaleFactor]; | |
+ width /= scaleFactor; | |
+ height /= scaleFactor;*/ | |
+ } | |
+ | |
if (bpp && (bpp == format->BitsPerPixel)) { | |
int hasMode = SDL_FALSE; | |
int i; | |
@@ -455,7 +474,7 @@ | |
list_size++; | |
if (client_mode_list == NULL) | |
- client_mode_list = (SDL_Rect**) | |
+ client_mode_list = (SDL_Rect**) | |
SDL_malloc (sizeof(*client_mode_list) * (list_size+1) ); | |
else { | |
/* !!! FIXME: this leaks memory if SDL_realloc() fails! */ | |
@@ -552,7 +571,7 @@ | |
CGContextRelease (cg_context); | |
cg_context = nil; | |
} | |
- | |
+ | |
/* Release fullscreen resources */ | |
if ( mode_flags & SDL_FULLSCREEN ) { | |
@@ -577,7 +596,7 @@ | |
qz_window = nil; | |
window_view = nil; | |
} | |
- /* | |
+ /* | |
Release the OpenGL context | |
Do this first to avoid trash on the display before fade | |
*/ | |
@@ -605,7 +624,7 @@ | |
/* Restore original screen resolution/bpp */ | |
QZ_RestoreDisplayMode (this); | |
CGReleaseAllDisplays (); | |
- /* | |
+ /* | |
Reset the main screen's rectangle | |
See comment in QZ_SetVideoFullscreen for why we do this | |
*/ | |
@@ -699,7 +718,7 @@ | |
if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { | |
CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); | |
} | |
- | |
+ | |
/* Destroy any previous mode */ | |
if (video_set == SDL_TRUE) | |
QZ_UnsetVideoMode (this, FALSE, save_gl); | |
@@ -726,7 +745,7 @@ | |
error = CGDisplayCapture (display_id); | |
else | |
error = CGCaptureAllDisplays (); | |
- | |
+ | |
if ( CGDisplayNoErr != error ) { | |
SDL_SetError ("Failed capturing display"); | |
goto ERR_NO_CAPTURE; | |
@@ -753,19 +772,19 @@ | |
/* Setup double-buffer emulation */ | |
if ( flags & SDL_DOUBLEBUF ) { | |
- | |
+ | |
/* | |
Setup a software backing store for reasonable results when | |
double buffering is requested (since a single-buffered hardware | |
surface looks hideous). | |
- | |
- The actual screen blit occurs in a separate thread to allow | |
+ | |
+ The actual screen blit occurs in a separate thread to allow | |
other blitting while waiting on the VBL (and hence results in higher framerates). | |
*/ | |
this->LockHWSurface = NULL; | |
this->UnlockHWSurface = NULL; | |
this->UpdateRects = NULL; | |
- | |
+ | |
current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); | |
this->UpdateRects = QZ_DoubleBufferUpdate; | |
this->LockHWSurface = QZ_LockDoubleBuffer; | |
@@ -777,10 +796,10 @@ | |
SDL_OutOfMemory (); | |
goto ERR_DOUBLEBUF; | |
} | |
- | |
+ | |
sw_buffers[0] = current->pixels; | |
sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; | |
- | |
+ | |
quit_thread = NO; | |
sem1 = SDL_CreateSemaphore (0); | |
sem2 = SDL_CreateSemaphore (1); | |
@@ -795,7 +814,7 @@ | |
/* Check if we should recreate the window */ | |
if (qz_window == nil) { | |
/* Manually create a window, avoids having a nib file resource */ | |
- qz_window = [ [ SDL_QuartzWindow alloc ] | |
+ qz_window = [ [ SDL_QuartzWindow alloc ] | |
initWithContentRect:contentRect | |
styleMask:(isLion ? NSBorderlessWindowMask : 0) | |
backing:NSBackingStoreBuffered | |
@@ -828,6 +847,10 @@ | |
/* Initialize the NSView and add it to our window. The presence of a valid window and | |
view allow the cursor to be changed whilst in fullscreen.*/ | |
window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; | |
+ if ( [window_view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:) ] ) | |
+ { | |
+ [ window_view setWantsBestResolutionOpenGLSurface:YES ]; | |
+ } | |
if ( isLion ) { | |
[ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; | |
@@ -852,7 +875,7 @@ | |
[ qz_window setLevel:NSNormalWindowLevel ]; | |
ctx = QZ_GetCGLContextObj (gl_context); | |
err = CGLSetFullScreen (ctx); | |
- | |
+ | |
if (err) { | |
SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); | |
goto ERR_NO_GL; | |
@@ -882,12 +905,12 @@ | |
cgColorspace = CGColorSpaceCreateDeviceRGB(); | |
current->pitch = 4 * current->w; | |
current->pixels = SDL_malloc (current->h * current->pitch); | |
- | |
+ | |
cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, | |
8, current->pitch, cgColorspace, | |
kCGImageAlphaNoneSkipFirst); | |
CGColorSpaceRelease (cgColorspace); | |
- | |
+ | |
current->flags |= SDL_SWSURFACE; | |
current->flags |= SDL_ASYNCBLIT; | |
current->hwdata = (void *) cg_context; | |
@@ -924,7 +947,7 @@ | |
CGReleaseDisplayFadeReservation(fade_token); | |
} | |
- /* | |
+ /* | |
There is a bug in Cocoa where NSScreen doesn't synchronize | |
with CGDirectDisplay, so the main screen's frame is wrong. | |
As a result, coordinate translation produces incorrect results. | |
@@ -967,11 +990,18 @@ | |
current->flags = 0; | |
current->w = width; | |
current->h = height; | |
- | |
+ | |
contentRect = NSMakeRect (0, 0, width, height); | |
+ // Adjust for retina | |
+ { | |
+ float scaleFactor = [[ NSScreen mainScreen ] backingScaleFactor]; | |
+ contentRect.size.width *= 1.0f / scaleFactor; | |
+ contentRect.size.height *= 1.0f / scaleFactor; | |
+ } | |
+ | |
/* | |
- Check if we should completely destroy the previous mode | |
+ Check if we should completely destroy the previous mode | |
- If it is fullscreen | |
- If it has different noframe or resizable attribute | |
- If it is OpenGL (since gl attributes could be different) | |
@@ -987,12 +1017,12 @@ | |
QZ_UnsetVideoMode (this, TRUE, save_gl); | |
} | |
else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || | |
- (mode_flags & SDL_OPENGL) || | |
+ (mode_flags & SDL_OPENGL) || | |
(flags & SDL_OPENGL) ) { | |
QZ_UnsetVideoMode (this, TRUE, save_gl); | |
} | |
} | |
- | |
+ | |
/* Sorry, QuickDraw was ripped out. */ | |
if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { | |
SDL_SetError ("Embedded QuickDraw windows are no longer supported"); | |
@@ -1005,7 +1035,7 @@ | |
/* Check if we should recreate the window */ | |
if (qz_window == nil) { | |
- | |
+ | |
/* Set the window style based on input flags */ | |
if ( flags & SDL_NOFRAME ) { | |
style = NSBorderlessWindowMask; | |
@@ -1020,12 +1050,12 @@ | |
} | |
/* Manually create a window, avoids having a nib file resource */ | |
- qz_window = [ [ SDL_QuartzWindow alloc ] | |
+ qz_window = [ [ SDL_QuartzWindow alloc ] | |
initWithContentRect:contentRect | |
- styleMask:style | |
+ styleMask:style | |
backing:NSBackingStoreBuffered | |
defer:NO ]; | |
- | |
+ | |
if (qz_window == nil) { | |
SDL_SetError ("Could not create the Cocoa window"); | |
if (fade_token != kCGDisplayFadeReservationInvalidToken) { | |
@@ -1074,6 +1104,11 @@ | |
window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; | |
[ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; | |
+ // MY RETINA ADDITION | |
+ if ( [window_view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:) ] ) | |
+ { | |
+ [ window_view setWantsBestResolutionOpenGLSurface:YES ]; | |
+ } | |
[ [ qz_window contentView ] addSubview:window_view ]; | |
[ gl_context setView: window_view ]; | |
[ window_view release ]; | |
@@ -1087,23 +1122,23 @@ | |
/* Only recreate the view if it doesn't already exist */ | |
if (window_view == nil) { | |
- | |
+ | |
window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; | |
[ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; | |
[ [ qz_window contentView ] addSubview:window_view ]; | |
[ window_view release ]; | |
[ qz_window makeKeyAndOrderFront:nil ]; | |
} | |
- | |
+ | |
cgColorspace = CGColorSpaceCreateDeviceRGB(); | |
current->pitch = 4 * current->w; | |
current->pixels = SDL_malloc (current->h * current->pitch); | |
- | |
+ | |
cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, | |
8, current->pitch, cgColorspace, | |
kCGImageAlphaNoneSkipFirst); | |
CGColorSpaceRelease (cgColorspace); | |
- | |
+ | |
current->flags |= SDL_SWSURFACE; | |
current->flags |= SDL_ASYNCBLIT; | |
current->hwdata = (void *) cg_context; | |
@@ -1287,9 +1322,9 @@ | |
UInt64 i; | |
Nanoseconds ns; | |
} temp; | |
- | |
+ | |
temp.i = seconds * 1000000000.0; | |
- | |
+ | |
return NanosecondsToAbsolute ( temp.ns ); | |
} | |
@@ -1297,7 +1332,7 @@ | |
{ | |
Uint8 *src, *dst; | |
int skip, len, h; | |
- | |
+ | |
/* | |
Give this thread the highest scheduling priority possible, | |
in the hopes that it will immediately run after the VBL delay | |
@@ -1306,20 +1341,20 @@ | |
pthread_t current_thread; | |
int policy; | |
struct sched_param param; | |
- | |
+ | |
current_thread = pthread_self (); | |
pthread_getschedparam (current_thread, &policy, ¶m); | |
policy = SCHED_RR; | |
param.sched_priority = sched_get_priority_max (policy); | |
pthread_setschedparam (current_thread, policy, ¶m); | |
} | |
- | |
+ | |
while (1) { | |
- | |
+ | |
SDL_SemWait (sem1); | |
if (quit_thread) | |
return 0; | |
- | |
+ | |
/* | |
* We have to add SDL_VideoSurface->offset here, since we might be a | |
* smaller surface in the center of the framebuffer (you asked for | |
@@ -1331,89 +1366,89 @@ | |
len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; | |
h = SDL_VideoSurface->h; | |
skip = SDL_VideoSurface->pitch; | |
- | |
+ | |
/* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ | |
{ | |
- | |
+ | |
/* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ | |
double refreshRate; | |
double linesPerSecond; | |
double target; | |
double position; | |
double adjustment; | |
- AbsoluteTime nextTime; | |
+ AbsoluteTime nextTime; | |
CFNumberRef refreshRateCFNumber; | |
- | |
+ | |
refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate); | |
if ( NULL == refreshRateCFNumber ) { | |
SDL_SetError ("Mode has no refresh rate"); | |
goto ERROR; | |
} | |
- | |
+ | |
if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) { | |
SDL_SetError ("Error getting refresh rate"); | |
goto ERROR; | |
} | |
- | |
+ | |
if ( 0 == refreshRate ) { | |
- | |
+ | |
SDL_SetError ("Display has no refresh rate, using 60hz"); | |
- | |
+ | |
/* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */ | |
refreshRate = 60.0; | |
} | |
- | |
+ | |
linesPerSecond = refreshRate * h; | |
target = h; | |
- | |
+ | |
/* Figure out the first delay so we start off about right */ | |
position = CGDisplayBeamPosition (display_id); | |
if (position > target) | |
position = 0; | |
- | |
- adjustment = (target - position) / linesPerSecond; | |
- | |
+ | |
+ adjustment = (target - position) / linesPerSecond; | |
+ | |
nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment)); | |
- | |
+ | |
MPDelayUntil (&nextTime); | |
} | |
- | |
- | |
+ | |
+ | |
/* On error, skip VBL delay */ | |
ERROR: | |
- | |
+ | |
/* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we | |
create two buffers, replace current_buffer with current_context and set it | |
appropriately in QZ_FlipDoubleBuffer. */ | |
while ( h-- ) { | |
- | |
+ | |
SDL_memcpy (dst, src, len); | |
src += skip; | |
dst += skip; | |
} | |
- | |
+ | |
/* signal flip completion */ | |
SDL_SemPost (sem2); | |
} | |
- | |
+ | |
return 0; | |
} | |
- | |
+ | |
static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface) | |
{ | |
/* wait for previous flip to complete */ | |
SDL_SemWait (sem2); | |
- | |
+ | |
current_buffer = surface->pixels; | |
- | |
+ | |
if (surface->pixels == sw_buffers[0]) | |
surface->pixels = sw_buffers[1]; | |
else | |
surface->pixels = sw_buffers[0]; | |
- | |
+ | |
/* signal worker thread to do the flip */ | |
SDL_SemPost (sem1); | |
- | |
+ | |
return 0; | |
} | |
@@ -1473,29 +1508,29 @@ | |
{ | |
/* Check if we should draw the resize icon */ | |
if (SDL_VideoSurface->flags & SDL_RESIZABLE) { | |
- | |
+ | |
SDL_Rect icon_rect; | |
- | |
+ | |
/* Create the icon image */ | |
if (resize_icon == NULL) { | |
- | |
+ | |
SDL_RWops *rw; | |
SDL_Surface *tmp; | |
- | |
+ | |
rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); | |
tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); | |
- | |
+ | |
resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); | |
SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); | |
- | |
+ | |
SDL_FreeSurface (tmp); | |
} | |
- | |
+ | |
icon_rect.x = SDL_VideoSurface->w - 13; | |
icon_rect.y = SDL_VideoSurface->h - 13; | |
icon_rect.w = 13; | |
icon_rect.h = 13; | |
- | |
+ | |
SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); | |
} | |
} | |
@@ -1506,10 +1541,10 @@ | |
QZ_GL_SwapBuffers (this); | |
} | |
else if ( [ qz_window isMiniaturized ] ) { | |
- | |
+ | |
/* Do nothing if miniaturized */ | |
} | |
- | |
+ | |
else { | |
NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; | |
if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */ | |
@@ -1521,7 +1556,7 @@ | |
CGContextFlush (cg_context); | |
CGImageRef image = CGBitmapContextCreateImage (cg_context); | |
CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height); | |
- | |
+ | |
CGContextDrawImage (cgc, rectangle, image); | |
CGImageRelease(image); | |
CGContextFlush (cgc); | |
@@ -1538,7 +1573,7 @@ | |
/* Ensure the cursor will be visible and working when we quit */ | |
CGDisplayShowCursor (display_id); | |
CGAssociateMouseAndMouseCursorPosition (1); | |
- | |
+ | |
if (mode_flags & SDL_FULLSCREEN) { | |
/* Fade to black to hide resolution-switching flicker (and garbage | |
that is displayed by a destroyed OpenGL context, if applicable) */ | |
diff -r 4488c8602961 src/video/quartz/SDL_QuartzWM.m | |
--- a/src/video/quartz/SDL_QuartzWM.m Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/src/video/quartz/SDL_QuartzWM.m Tue Apr 09 07:45:32 2013 +1000 | |
@@ -150,7 +150,9 @@ | |
void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { | |
if ( ! CGDisplayIsCaptured (display_id) ) | |
+ { | |
*p = [ qz_window convertScreenToBase:*p ]; | |
+ } | |
} | |
@@ -234,6 +236,8 @@ | |
CGPoint cgp; | |
p = NSMakePoint (x, y); | |
+ // RETINA: convert from pixels to points | |
+ p = [ window_view convertPointFromBacking:p ]; | |
cgp = QZ_PrivateSDLToCG (this, &p); | |
/* this is the magic call that fixes cursor "freezing" after warp */ | |
diff -r 4488c8602961 src/video/quartz/SDL_QuartzWindow.m | |
--- a/src/video/quartz/SDL_QuartzWindow.m Wed Jul 18 14:14:55 2012 -0700 | |
+++ b/src/video/quartz/SDL_QuartzWindow.m Tue Apr 09 07:45:32 2013 +1000 | |
@@ -123,7 +123,13 @@ | |
[ super setFrame:frameRect display:flag ]; | |
newViewFrame = [ window_view frame ]; | |
- | |
+ // Adjust for retina | |
+ { | |
+ float scaleFactor = [[ NSScreen mainScreen ] backingScaleFactor]; | |
+ newViewFrame.size.width *= scaleFactor; | |
+ newViewFrame.size.height *= scaleFactor; | |
+ } | |
+ | |
SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment