Use a buffered window. This fixes the last of the GUI issues. Allows resizing and is very careful to update the graphics context only in the main thread (in this case, SM's main thread, not the GUI thread). It does so by managing the NSOpenGLContext explicitly rather than using NSOpenGLView to do it for us.
This commit is contained in:
@@ -14,7 +14,7 @@ class LowLevelWindow_Cocoa : public LowLevelWindow
|
|||||||
{
|
{
|
||||||
VideoModeParams mCurrentParams;
|
VideoModeParams mCurrentParams;
|
||||||
id mWindow;
|
id mWindow;
|
||||||
id mView;
|
id mWindowContext;
|
||||||
id mFullScreenContext;
|
id mFullScreenContext;
|
||||||
bool mSharingContexts;
|
bool mSharingContexts;
|
||||||
CFDictionaryRef mCurrentDisplayMode;
|
CFDictionaryRef mCurrentDisplayMode;
|
||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
CString TryVideoMode( const VideoModeParams& p, bool& newDeviceOut );
|
CString TryVideoMode( const VideoModeParams& p, bool& newDeviceOut );
|
||||||
void GetDisplayResolutions( DisplayResolutions &dr ) const;
|
void GetDisplayResolutions( DisplayResolutions &dr ) const;
|
||||||
void SwapBuffers();
|
void SwapBuffers();
|
||||||
|
void Update();
|
||||||
|
|
||||||
VideoModeParams GetActualVideoModeParams() const { return mCurrentParams; }
|
VideoModeParams GetActualVideoModeParams() const { return mCurrentParams; }
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#import "DisplayResolutions.h"
|
#import "DisplayResolutions.h"
|
||||||
#import "RageLog.h"
|
#import "RageLog.h"
|
||||||
#import "RageUtil.h"
|
#import "RageUtil.h"
|
||||||
|
#import "RageThreads.h"
|
||||||
#import "arch/ArchHooks/ArchHooks.h"
|
#import "arch/ArchHooks/ArchHooks.h"
|
||||||
#import "archutils/Darwin/SMMainThread.h"
|
#import "archutils/Darwin/SMMainThread.h"
|
||||||
|
|
||||||
@@ -10,7 +11,12 @@
|
|||||||
#import <OpenGl/OpenGl.h>
|
#import <OpenGl/OpenGl.h>
|
||||||
#import <mach-o/dyld.h>
|
#import <mach-o/dyld.h>
|
||||||
|
|
||||||
static const int g_iStyleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
|
static const unsigned int g_iStyleMask = NSTitledWindowMask | NSClosableWindowMask |
|
||||||
|
NSMiniaturizableWindowMask | NSResizableWindowMask;
|
||||||
|
static bool g_bResized;
|
||||||
|
static int g_iWidth;
|
||||||
|
static int g_iHeight;
|
||||||
|
static RageMutex g_ResizeLock( "Window resize lock." );
|
||||||
|
|
||||||
// Simple helper class
|
// Simple helper class
|
||||||
class AutoreleasePool
|
class AutoreleasePool
|
||||||
@@ -32,6 +38,7 @@ public:
|
|||||||
- (void) windowDidBecomeKey:(NSNotification *)aNotification;
|
- (void) windowDidBecomeKey:(NSNotification *)aNotification;
|
||||||
- (void) windowDidResignKey:(NSNotification *)aNotification;
|
- (void) windowDidResignKey:(NSNotification *)aNotification;
|
||||||
- (void) windowWillClose:(NSNotification *)aNotification;
|
- (void) windowWillClose:(NSNotification *)aNotification;
|
||||||
|
- (void) windowDidResize:(NSNotification *)aNotification;
|
||||||
// XXX maybe use whichever screen contains the window? Hard for me to test though.
|
// XXX maybe use whichever screen contains the window? Hard for me to test though.
|
||||||
//- (void) windowDidChangeScreen:(NSNotification *)aNotification;
|
//- (void) windowDidChangeScreen:(NSNotification *)aNotification;
|
||||||
@end
|
@end
|
||||||
@@ -51,9 +58,21 @@ public:
|
|||||||
{
|
{
|
||||||
ArchHooks::SetUserQuit();
|
ArchHooks::SetUserQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) windowDidResize:(NSNotification *)aNotification
|
||||||
|
{
|
||||||
|
id window = [aNotification object];
|
||||||
|
NSSize size = [NSWindow contentRectForFrameRect:[window frame] styleMask:g_iStyleMask].size;
|
||||||
|
|
||||||
|
LockMut( g_ResizeLock );
|
||||||
|
g_bResized = true;
|
||||||
|
g_iWidth = int( size.width );
|
||||||
|
g_iHeight = int( size.height );
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
LowLevelWindow_Cocoa::LowLevelWindow_Cocoa() : mView(nil), mFullScreenContext(nil), mCurrentDisplayMode(NULL)
|
LowLevelWindow_Cocoa::LowLevelWindow_Cocoa() : mWindowContext(nil), mFullScreenContext(nil), mCurrentDisplayMode(NULL)
|
||||||
{
|
{
|
||||||
POOL;
|
POOL;
|
||||||
NSRect rect = { {0, 0}, {0, 0} };
|
NSRect rect = { {0, 0}, {0, 0} };
|
||||||
@@ -61,9 +80,8 @@ LowLevelWindow_Cocoa::LowLevelWindow_Cocoa() : mView(nil), mFullScreenContext(ni
|
|||||||
|
|
||||||
mWindow = [[NSWindow alloc] initWithContentRect:rect
|
mWindow = [[NSWindow alloc] initWithContentRect:rect
|
||||||
styleMask:g_iStyleMask
|
styleMask:g_iStyleMask
|
||||||
backing:NSBackingStoreNonretained
|
backing:NSBackingStoreBuffered
|
||||||
defer:YES];
|
defer:YES];
|
||||||
ASSERT( mWindow != nil );
|
|
||||||
|
|
||||||
ADD_ACTIONb( mt, mWindow, setExcludedFromWindowsMenu:, YES );
|
ADD_ACTIONb( mt, mWindow, setExcludedFromWindowsMenu:, YES );
|
||||||
ADD_ACTIONb( mt, mWindow, useOptimizedDrawing:, YES );
|
ADD_ACTIONb( mt, mWindow, useOptimizedDrawing:, YES );
|
||||||
@@ -90,9 +108,11 @@ LowLevelWindow_Cocoa::~LowLevelWindow_Cocoa()
|
|||||||
ADD_ACTION1( mt, mWindow, orderOut:, nil );
|
ADD_ACTION1( mt, mWindow, orderOut:, nil );
|
||||||
ADD_ACTION0( mt, mWindow, release );
|
ADD_ACTION0( mt, mWindow, release );
|
||||||
|
|
||||||
|
[mWindowContext clearDrawable];
|
||||||
[mt performOnMainThread];
|
[mt performOnMainThread];
|
||||||
[delegate release];
|
[delegate release];
|
||||||
[mt release];
|
[mt release];
|
||||||
|
[mWindowContext release];
|
||||||
[mFullScreenContext release];
|
[mFullScreenContext release];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +168,7 @@ CString LowLevelWindow_Cocoa::TryVideoMode( const VideoModeParams& p, bool& newD
|
|||||||
|
|
||||||
ASSERT( p.bpp == 16 || p.bpp == 32 );
|
ASSERT( p.bpp == 16 || p.bpp == 32 );
|
||||||
|
|
||||||
if( p.bpp != mCurrentParams.bpp || !mView )
|
if( p.bpp != mCurrentParams.bpp || !mWindowContext )
|
||||||
{
|
{
|
||||||
NSOpenGLPixelFormat *pixelFormat;
|
NSOpenGLPixelFormat *pixelFormat;
|
||||||
NSOpenGLPixelFormatAttribute attrs[] = {
|
NSOpenGLPixelFormatAttribute attrs[] = {
|
||||||
@@ -159,7 +179,6 @@ CString LowLevelWindow_Cocoa::TryVideoMode( const VideoModeParams& p, bool& newD
|
|||||||
NSOpenGLPFAColorSize, NSOpenGLPixelFormatAttribute(p.bpp == 16 ? 16 : 24),
|
NSOpenGLPFAColorSize, NSOpenGLPixelFormatAttribute(p.bpp == 16 ? 16 : 24),
|
||||||
NSOpenGLPixelFormatAttribute(0)
|
NSOpenGLPixelFormatAttribute(0)
|
||||||
};
|
};
|
||||||
id nextView;
|
|
||||||
|
|
||||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
||||||
|
|
||||||
@@ -168,36 +187,37 @@ CString LowLevelWindow_Cocoa::TryVideoMode( const VideoModeParams& p, bool& newD
|
|||||||
[mt performOnMainThread];
|
[mt performOnMainThread];
|
||||||
return "Failed to set the windowed pixel format.";
|
return "Failed to set the windowed pixel format.";
|
||||||
}
|
}
|
||||||
nextView = [[[NSOpenGLView alloc] initWithFrame:contentRect pixelFormat:pixelFormat] autorelease];
|
id nextContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
|
||||||
[pixelFormat release];
|
[pixelFormat release];
|
||||||
if( nextView == nil )
|
if( nextContext == nil )
|
||||||
{
|
{
|
||||||
[mt performOnMainThread];
|
[mt performOnMainThread];
|
||||||
return "Failed to create windowed OGL context.";
|
return "Failed to create windowed OGL context.";
|
||||||
}
|
}
|
||||||
SetOGLParameters( [mView openGLContext] );
|
SetOGLParameters( nextContext );
|
||||||
newDeviceOut = true;
|
newDeviceOut = true;
|
||||||
mView = nextView;
|
[mWindowContext clearDrawable];
|
||||||
ADD_ACTION1( mt, mWindow, setContentView:, mView );
|
[mWindowContext release];
|
||||||
|
mWindowContext = nextContext;
|
||||||
|
|
||||||
// We need to recreate the full screen context as well.
|
// We need to recreate the full screen context as well.
|
||||||
[mFullScreenContext clearDrawable];
|
[mFullScreenContext clearDrawable];
|
||||||
[mFullScreenContext release];
|
[mFullScreenContext release];
|
||||||
mFullScreenContext = nil;
|
mFullScreenContext = nil;
|
||||||
mCurrentParams.bpp = p.bpp;
|
mCurrentParams.bpp = p.bpp;
|
||||||
|
mSharingContexts = false;
|
||||||
}
|
}
|
||||||
if( p.windowed )
|
if( p.windowed )
|
||||||
{
|
{
|
||||||
id context = [mView openGLContext];
|
|
||||||
|
|
||||||
ShutDownFullScreen();
|
ShutDownFullScreen();
|
||||||
|
|
||||||
ADD_ACTION0( mt, mWindow, center );
|
ADD_ACTION0( mt, mWindow, center );
|
||||||
ADD_ACTION1( mt, mWindow, makeKeyAndOrderFront:, nil );
|
ADD_ACTION1( mt, mWindow, makeKeyAndOrderFront:, nil );
|
||||||
|
|
||||||
[mt performOnMainThread];
|
[mt performOnMainThread];
|
||||||
[context update];
|
[mWindowContext setView:[mWindow contentView]];
|
||||||
[context makeCurrentContext];
|
[mWindowContext update];
|
||||||
|
[mWindowContext makeCurrentContext];
|
||||||
mCurrentParams.windowed = true;
|
mCurrentParams.windowed = true;
|
||||||
SetActualParamsFromMode( CGDisplayCurrentMode(kCGDirectMainDisplay) );
|
SetActualParamsFromMode( CGDisplayCurrentMode(kCGDirectMainDisplay) );
|
||||||
|
|
||||||
@@ -236,8 +256,7 @@ CString LowLevelWindow_Cocoa::TryVideoMode( const VideoModeParams& p, bool& newD
|
|||||||
return "Failed to set full screen pixel format.";
|
return "Failed to set full screen pixel format.";
|
||||||
}
|
}
|
||||||
|
|
||||||
mFullScreenContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
|
mFullScreenContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:mWindowContext];
|
||||||
shareContext:[mView openGLContext]];
|
|
||||||
if( !(mSharingContexts = mFullScreenContext != nil) )
|
if( !(mSharingContexts = mFullScreenContext != nil) )
|
||||||
{
|
{
|
||||||
LOG->Warn( "Failed to share openGL contexts." );
|
LOG->Warn( "Failed to share openGL contexts." );
|
||||||
@@ -371,5 +390,21 @@ void LowLevelWindow_Cocoa::GetDisplayResolutions( DisplayResolutions &dr ) const
|
|||||||
|
|
||||||
void LowLevelWindow_Cocoa::SwapBuffers()
|
void LowLevelWindow_Cocoa::SwapBuffers()
|
||||||
{
|
{
|
||||||
[[NSOpenGLContext currentContext] flushBuffer];
|
[(mCurrentParams.windowed ? mWindowContext : mFullScreenContext) flushBuffer];
|
||||||
|
}
|
||||||
|
|
||||||
|
void LowLevelWindow_Cocoa::Update()
|
||||||
|
{
|
||||||
|
LockMutex lock( g_ResizeLock );
|
||||||
|
if( likely(!g_bResized) )
|
||||||
|
return;
|
||||||
|
LOG->Trace( "LLW_Cocoa::Update(): %d x %d", mCurrentParams.width, mCurrentParams.height );
|
||||||
|
if( mCurrentParams.width == g_iWidth && mCurrentParams.height == g_iHeight )
|
||||||
|
return;
|
||||||
|
mCurrentParams.width = g_iWidth;
|
||||||
|
mCurrentParams.height = g_iHeight;
|
||||||
|
g_bResized = false;
|
||||||
|
lock.Unlock(); // Unlock before calling ResolutionChanged().
|
||||||
|
[mWindowContext update];
|
||||||
|
DISPLAY->ResolutionChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user