* - http://developer.apple.com/library/mac/#samplecode/glut/Introduction/Intro.html
* - http://developer.apple.com/library/mac/#samplecode/GLEssentials/Introduction/Intro.html
* - http://www.glfw.org/
+ * - http://cocoasamurai.blogspot.co.uk/2008/04/guide-to-threading-on-leopard.html
+ * - http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html
*/
#include <Cocoa/Cocoa.h>
+#include "os_thread.hpp"
#include "glws.hpp"
+/**
+ * Dummy thread to force Cocoa to enter multithreading mode.
+ */
+@interface DummyThread : NSObject
+ + (void)enterMultiThreaded;
+ + (void)dummyThreadMethod:(id)unused;
+@end
+
+@implementation DummyThread
+ + (void)dummyThreadMethod:(id)unused {
+ (void)unused;
+ }
+
+ + (void)enterMultiThreaded {
+ [NSThread detachNewThreadSelector:@selector(dummyThreadMethod:)
+ toTarget:self
+ withObject:nil];
+ }
+@end
+
+
namespace glws {
-NSAutoreleasePool *autoreleasePool = nil;
+static OS_THREAD_SPECIFIC_PTR(NSAutoreleasePool)
+autoreleasePool;
class CocoaVisual : public Visual
{
public:
NSWindow *window;
+ NSOpenGLView *view;
NSOpenGLContext *currentContext;
CocoaDrawable(const Visual *vis, int w, int h, bool pbuffer) :
defer:NO];
assert(window != nil);
- NSOpenGLView *view = [[NSOpenGLView alloc]
- initWithFrame:winRect
- pixelFormat:pixelFormat];
+ view = [[NSOpenGLView alloc]
+ initWithFrame:winRect
+ pixelFormat:pixelFormat];
assert(view != nil);
[window setContentView:view];
if (currentContext != nil) {
[currentContext update];
[window makeKeyAndOrderFront:nil];
- [currentContext setView:[window contentView]];
+ [currentContext setView:view];
[currentContext makeCurrentContext];
}
};
+static inline void
+initThread(void) {
+ if (autoreleasePool == nil) {
+ autoreleasePool = [[NSAutoreleasePool alloc] init];
+ }
+}
+
void
init(void) {
// Prevent glproc to load system's OpenGL, so that we can trace glretrace.
_libGlHandle = dlopen("OpenGL", RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
- [NSApplication sharedApplication];
+ initThread();
+
+ [DummyThread enterMultiThreaded];
- autoreleasePool = [[NSAutoreleasePool alloc] init];
+ bool isMultiThreaded = [NSThread isMultiThreaded];
+ if (!isMultiThreaded) {
+ std::cerr << "error: failed to enable Cocoa multi-threading\n";
+ exit(1);
+ }
+
+ [NSApplication sharedApplication];
[NSApp finishLaunching];
}
Visual *
createVisual(bool doubleBuffer, Profile profile) {
+
+ initThread();
+
if (profile != PROFILE_COMPAT &&
profile != PROFILE_CORE) {
return nil;
Drawable *
createDrawable(const Visual *visual, int width, int height, bool pbuffer)
{
+ initThread();
+
return new CocoaDrawable(visual, width, height, pbuffer);
}
Context *
createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug)
{
+ initThread();
+
NSOpenGLPixelFormat *pixelFormat = static_cast<const CocoaVisual *>(visual)->pixelFormat;
NSOpenGLContext *share_context = nil;
NSOpenGLContext *context;
bool
makeCurrent(Drawable *drawable, Context *context)
{
+ initThread();
+
if (!drawable || !context) {
[NSOpenGLContext clearCurrentContext];
} else {
bool
processEvents(void) {
- NSEvent* event;
+ initThread();
+ NSEvent* event;
do {
event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]