Browse Source

new Cocoa graphics pipe is now fully functional

rdb 13 years ago
parent
commit
1f0304c696

+ 13 - 6
panda/src/cocoadisplay/cocoaGraphicsPipe.mm

@@ -21,6 +21,7 @@
 
 
 #import <Foundation/NSAutoreleasePool.h>
 #import <Foundation/NSAutoreleasePool.h>
 #import <AppKit/NSApplication.h>
 #import <AppKit/NSApplication.h>
+#import <AppKit/NSRunningApplication.h>
 
 
 #include <mach-o/arch.h>
 #include <mach-o/arch.h>
 
 
@@ -31,9 +32,15 @@ static void init_app() {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     [NSApplication sharedApplication];
     [NSApplication sharedApplication];
 
 
-    [NSApp setActivationPolicy:nil];
+    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
     [NSApp finishLaunching];
     [NSApp finishLaunching];
     [NSApp activateIgnoringOtherApps:YES];
     [NSApp activateIgnoringOtherApps:YES];
+    
+    // Put Cocoa into thread-safe mode
+    // by spawning a thread which immediately exits.
+    NSThread* thread = [[NSThread alloc] init];
+    [thread start];
+    [thread autorelease]; 
   }
   }
 }
 }
 
 
@@ -264,7 +271,7 @@ pipe_constructor() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsPipe::PreferredWindowThread
 GraphicsPipe::PreferredWindowThread
 CocoaGraphicsPipe::get_preferred_window_thread() const {
 CocoaGraphicsPipe::get_preferred_window_thread() const {
-  // The NSView and NSWindow classes are not thread-safe,
+  // The NSView and NSWindow classes are not completely thread-safe,
   // they can only be called from the main thread!
   // they can only be called from the main thread!
   return PWT_app;
   return PWT_app;
 }
 }
@@ -309,8 +316,8 @@ make_output(const string &name,
     return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
     return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
                                    flags, gsg, host);
                                    flags, gsg, host);
   }
   }
-/*
-  // Second thing to try: a GLES(2)GraphicsBuffer
+
+  // Second thing to try: a GLGraphicsBuffer
   if (retry == 1) {
   if (retry == 1) {
     if ((host==0)||
     if ((host==0)||
   //        (!gl_support_fbo)||
   //        (!gl_support_fbo)||
@@ -334,7 +341,7 @@ make_output(const string &name,
         (cocoagsg->is_valid()) &&
         (cocoagsg->is_valid()) &&
         (!cocoagsg->needs_reset()) &&
         (!cocoagsg->needs_reset()) &&
         (cocoagsg->_supports_framebuffer_object) &&
         (cocoagsg->_supports_framebuffer_object) &&
-        (cocoagsg->_glDrawBuffers != 0)&&
+        (cocoagsg->_glDrawBuffers != 0) &&
         (fb_prop.is_basic())) {
         (fb_prop.is_basic())) {
       precertify = true;
       precertify = true;
     }
     }
@@ -342,7 +349,7 @@ make_output(const string &name,
     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
                                 flags, gsg, host);
                                 flags, gsg, host);
   }
   }
-
+/*
   // Third thing to try: a CocoaGraphicsBuffer
   // Third thing to try: a CocoaGraphicsBuffer
   if (retry == 2) {
   if (retry == 2) {
     if (((flags&BF_require_parasite)!=0)||
     if (((flags&BF_require_parasite)!=0)||

+ 1 - 1
panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h

@@ -33,7 +33,7 @@ public:
                       NSOpenGLPixelFormat *pixel_format, int virtual_screen);
                       NSOpenGLPixelFormat *pixel_format, int virtual_screen);
   void choose_pixel_format(const FrameBufferProperties &properties,
   void choose_pixel_format(const FrameBufferProperties &properties,
                            CGDirectDisplayID display,
                            CGDirectDisplayID display,
-                           bool need_window, bool need_pbuffer);
+                           bool need_pbuffer);
 
 
   CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
   CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
                              CocoaGraphicsStateGuardian *share_with);
                              CocoaGraphicsStateGuardian *share_with);

+ 54 - 32
panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm

@@ -17,6 +17,7 @@
 #include "lightReMutexHolder.h"
 #include "lightReMutexHolder.h"
 
 
 #include <mach-o/dyld.h>
 #include <mach-o/dyld.h>
+#import <AppKit/AppKit.h>
 #import <OpenGL/CGLRenderers.h>
 #import <OpenGL/CGLRenderers.h>
 
 
 TypeHandle CocoaGraphicsStateGuardian::_type_handle;
 TypeHandle CocoaGraphicsStateGuardian::_type_handle;
@@ -69,20 +70,20 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
     depth_size, stencil_size, accum_size, sample_buffers, samples,
     depth_size, stencil_size, accum_size, sample_buffers, samples,
     renderer_id, accelerated, window, pbuffer;
     renderer_id, accelerated, window, pbuffer;
 
 
-  [pixel_format getValues: &double_buffer forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: screen];
-  [pixel_format getValues: &stereo forAttribute: NSOpenGLPFAStereo forVirtualScreen: screen];
-  [pixel_format getValues: &aux_buffers forAttribute: NSOpenGLPFAAuxBuffers forVirtualScreen: screen];
-  [pixel_format getValues: &color_size forAttribute: NSOpenGLPFAColorSize forVirtualScreen: screen];
-  [pixel_format getValues: &alpha_size forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: screen];
-  [pixel_format getValues: &depth_size forAttribute: NSOpenGLPFADepthSize forVirtualScreen: screen];
-  [pixel_format getValues: &stencil_size forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: screen];
-  [pixel_format getValues: &accum_size forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: screen];
-  [pixel_format getValues: &sample_buffers forAttribute: NSOpenGLPFASampleBuffers forVirtualScreen: screen];
-  [pixel_format getValues: &samples forAttribute: NSOpenGLPFASamples forVirtualScreen: screen];
-  [pixel_format getValues: &renderer_id forAttribute: NSOpenGLPFARendererID forVirtualScreen: screen];
-  [pixel_format getValues: &accelerated forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: screen];
-  [pixel_format getValues: &window forAttribute: NSOpenGLPFAWindow forVirtualScreen: screen];
-  [pixel_format getValues: &pbuffer forAttribute: NSOpenGLPFAPixelBuffer forVirtualScreen: screen];
+  [pixel_format getValues:&double_buffer  forAttribute:NSOpenGLPFADoubleBuffer  forVirtualScreen:screen];
+  [pixel_format getValues:&stereo         forAttribute:NSOpenGLPFAStereo        forVirtualScreen:screen];
+  [pixel_format getValues:&aux_buffers    forAttribute:NSOpenGLPFAAuxBuffers    forVirtualScreen:screen];
+  [pixel_format getValues:&color_size     forAttribute:NSOpenGLPFAColorSize     forVirtualScreen:screen];
+  [pixel_format getValues:&alpha_size     forAttribute:NSOpenGLPFAAlphaSize     forVirtualScreen:screen];
+  [pixel_format getValues:&depth_size     forAttribute:NSOpenGLPFADepthSize     forVirtualScreen:screen];
+  [pixel_format getValues:&stencil_size   forAttribute:NSOpenGLPFAStencilSize   forVirtualScreen:screen];
+  [pixel_format getValues:&accum_size     forAttribute:NSOpenGLPFAAccumSize     forVirtualScreen:screen];
+  [pixel_format getValues:&sample_buffers forAttribute:NSOpenGLPFASampleBuffers forVirtualScreen:screen];
+  [pixel_format getValues:&samples        forAttribute:NSOpenGLPFASamples       forVirtualScreen:screen];
+  [pixel_format getValues:&renderer_id    forAttribute:NSOpenGLPFARendererID    forVirtualScreen:screen];
+  [pixel_format getValues:&accelerated    forAttribute:NSOpenGLPFAAccelerated   forVirtualScreen:screen];
+  [pixel_format getValues:&window         forAttribute:NSOpenGLPFAWindow        forVirtualScreen:screen];
+  [pixel_format getValues:&pbuffer        forAttribute:NSOpenGLPFAPixelBuffer   forVirtualScreen:screen];
 
 
   properties.set_back_buffers(double_buffer);
   properties.set_back_buffers(double_buffer);
   properties.set_stereo(stereo);
   properties.set_stereo(stereo);
@@ -97,11 +98,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
   }
   }
   //TODO: add aux buffers
   //TODO: add aux buffers
 
 
+  // Extract the renderer ID bits and check if our
+  // renderer matches the known software renderers.
+  renderer_id &= kCGLRendererIDMatchingMask;
   if (renderer_id == kCGLRendererGenericID ||
   if (renderer_id == kCGLRendererGenericID ||
       renderer_id == kCGLRendererGenericFloatID ||
       renderer_id == kCGLRendererGenericFloatID ||
       renderer_id == kCGLRendererAppleSWID) {
       renderer_id == kCGLRendererAppleSWID) {
+
     properties.set_force_software(1);
     properties.set_force_software(1);
   }
   }
+
   if (accelerated) {
   if (accelerated) {
     properties.set_force_hardware(1);
     properties.set_force_hardware(1);
   }
   }
@@ -117,16 +123,16 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
 void CocoaGraphicsStateGuardian::
 void CocoaGraphicsStateGuardian::
 choose_pixel_format(const FrameBufferProperties &properties,
 choose_pixel_format(const FrameBufferProperties &properties,
                     CGDirectDisplayID display,
                     CGDirectDisplayID display,
-                    bool need_window, bool need_pbuffer) {
+                    bool need_pbuffer) {
 
 
   _context = nil;
   _context = nil;
   _fbprops.clear();
   _fbprops.clear();
 
 
   // Neither Cocoa nor CGL seem to have a mechanism to query the available
   // Neither Cocoa nor CGL seem to have a mechanism to query the available
-  // pixel formats, unfortunately, so the only thing we can do is ask for one
-  // with the properties we have requested.
+  // pixel formats, unfortunately, so the only thing we can do is ask for
+  // one with the properties we have requested.
   pvector<NSOpenGLPixelFormatAttribute> attribs;
   pvector<NSOpenGLPixelFormatAttribute> attribs;
-  attribs.reserve(13);
+  attribs.reserve(15);
 
 
   // Picked this up from the pyglet source - seems
   // Picked this up from the pyglet source - seems
   // to be necessary to support RAGE-II, which is not compliant.
   // to be necessary to support RAGE-II, which is not compliant.
@@ -135,8 +141,9 @@ choose_pixel_format(const FrameBufferProperties &properties,
   // Don't let it fall back to a different renderer.
   // Don't let it fall back to a different renderer.
   attribs.push_back(NSOpenGLPFANoRecovery);
   attribs.push_back(NSOpenGLPFANoRecovery);
   
   
-  // Selection policy.
-  //attribs.push_back(NSOpenGLPFAMinimumPolicy);
+  // Consider pixel formats with properties equal
+  // to or better than we requested.
+  attribs.push_back(NSOpenGLPFAMinimumPolicy);
 
 
   if (!properties.is_single_buffered()) {
   if (!properties.is_single_buffered()) {
     attribs.push_back(NSOpenGLPFADoubleBuffer);
     attribs.push_back(NSOpenGLPFADoubleBuffer);
@@ -151,13 +158,22 @@ choose_pixel_format(const FrameBufferProperties &properties,
   attribs.push_back(aux_buffers);
   attribs.push_back(aux_buffers);
   attribs.push_back(NSOpenGLPFAColorSize);
   attribs.push_back(NSOpenGLPFAColorSize);
   attribs.push_back(properties.get_color_bits());
   attribs.push_back(properties.get_color_bits());
-  attribs.push_back(NSOpenGLPFAAlphaSize);
-  attribs.push_back(properties.get_alpha_bits());
   attribs.push_back(NSOpenGLPFADepthSize);
   attribs.push_back(NSOpenGLPFADepthSize);
   attribs.push_back(properties.get_depth_bits());
   attribs.push_back(properties.get_depth_bits());
   attribs.push_back(NSOpenGLPFAStencilSize);
   attribs.push_back(NSOpenGLPFAStencilSize);
   attribs.push_back(properties.get_stencil_bits());
   attribs.push_back(properties.get_stencil_bits());
 
 
+  // Curious case - if we request anything less than 8 alpha bits,
+  // then on some ATI cards, it will grab a pixel format with just
+  // 2 alpha bits, which just shows a white window and nothing else.
+  // Might have something to do with the compositing window manager.
+  // Omitting it altogether seems to make it grab one with 8 bits, though.
+  // Dirty hack.  Needs more research.
+  if (properties.get_alpha_bits() > 0) {
+    attribs.push_back(NSOpenGLPFAAlphaSize);
+    attribs.push_back(max(8, properties.get_alpha_bits()));
+  }
+
   if (properties.get_multisamples() > 0) {
   if (properties.get_multisamples() > 0) {
     attribs.push_back(NSOpenGLPFASampleBuffers);
     attribs.push_back(NSOpenGLPFASampleBuffers);
     attribs.push_back(1);
     attribs.push_back(1);
@@ -167,19 +183,16 @@ choose_pixel_format(const FrameBufferProperties &properties,
   }
   }
 
 
   if (properties.get_force_software()) {
   if (properties.get_force_software()) {
+    // Request the generic software renderer.
     attribs.push_back(NSOpenGLPFARendererID);
     attribs.push_back(NSOpenGLPFARendererID);
-    attribs.push_back(kCGLRendererAppleSWID);
+    attribs.push_back(kCGLRendererGenericFloatID);
   }
   }
   
   
   if (properties.get_force_hardware()) {
   if (properties.get_force_hardware()) {
     attribs.push_back(NSOpenGLPFAAccelerated);
     attribs.push_back(NSOpenGLPFAAccelerated);
   }
   }
 
 
-  if (need_window) {
-    //TODO: when to request fullscreen on Cocoa?
-    attribs.push_back(NSOpenGLPFAWindow);
-    //attribs.push_back(NSOpenGLPFAFullScreen);
-  }
+  attribs.push_back(NSOpenGLPFAWindow);
 
 
   if (need_pbuffer) {
   if (need_pbuffer) {
     attribs.push_back(NSOpenGLPFAPixelBuffer);
     attribs.push_back(NSOpenGLPFAPixelBuffer);
@@ -189,19 +202,25 @@ choose_pixel_format(const FrameBufferProperties &properties,
   attribs.push_back(NSOpenGLPFAScreenMask);
   attribs.push_back(NSOpenGLPFAScreenMask);
   attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display));
   attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display));
 
 
+  // End of the array
   attribs.push_back((NSOpenGLPixelFormatAttribute) nil);
   attribs.push_back((NSOpenGLPixelFormatAttribute) nil);
 
 
   // Create the format.
   // Create the format.
-  NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: &attribs[0]];
+  NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
   if (format == nil) {
   if (format == nil) {
     cocoadisplay_cat.error() <<
     cocoadisplay_cat.error() <<
       "Could not find a usable pixel format.\n";
       "Could not find a usable pixel format.\n";
     return;
     return;
   }
   }
 
 
-  //XXX not sure what to do with virtual_screen, let's just set it to 0.
+  // For now, I'm just using the first virtual screen.
+  cocoadisplay_cat.debug() <<
+    "Pixel format has " << [format numberOfVirtualScreens] << " virtual screens.\n";
   get_properties(_fbprops, format, 0);
   get_properties(_fbprops, format, 0);
-  _context = [[NSOpenGLContext alloc] initWithFormat: format shareContext: _share_context];
+
+  //TODO: print out renderer
+
+  _context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:_share_context];
   [format release];
   [format release];
   if (_context == nil) {
   if (_context == nil) {
     cocoadisplay_cat.error() <<
     cocoadisplay_cat.error() <<
@@ -230,6 +249,9 @@ query_gl_version() {
   // where the GL version has been output, and it's nice to see the
   // where the GL version has been output, and it's nice to see the
   // two of these together.
   // two of these together.
   if (glgsg_cat.is_debug()) {
   if (glgsg_cat.is_debug()) {
+    //XXX this is supposed to work, but the NSOpenGLGetVersion
+    // symbol cannot be found when I do this
+
     //GLint major, minor;
     //GLint major, minor;
     //NSOpenGLGetVersion(&major, &minor);
     //NSOpenGLGetVersion(&major, &minor);
 
 
@@ -264,7 +286,7 @@ do_get_extension_func(const char *prefix, const char *name) {
     return (void *) NSAddressOfSymbol(symbol);
     return (void *) NSAddressOfSymbol(symbol);
   }
   }
 
 
-  cocoadisplay_cat.error() <<
+  cocoadisplay_cat.warning() <<
     "do_get_extension_func failed for " << prefix << name << "!\n";
     "do_get_extension_func failed for " << prefix << name << "!\n";
 
 
   free(fullname);
   free(fullname);

+ 1 - 1
panda/src/cocoadisplay/cocoaGraphicsWindow.h

@@ -56,7 +56,7 @@ public:
   void handle_close_event();
   void handle_close_event();
   void handle_key_event(NSEvent *event);
   void handle_key_event(NSEvent *event);
   void handle_mouse_button_event(int button, bool down);
   void handle_mouse_button_event(int button, bool down);
-  void handle_mouse_moved_event(bool in_window, int x, int y, bool absolute);
+  void handle_mouse_moved_event(bool in_window, double x, double y, bool absolute);
   void handle_wheel_event(double x, double y);
   void handle_wheel_event(double x, double y);
 
 
   INLINE NSWindow *get_nswindow() const;
   INLINE NSWindow *get_nswindow() const;

+ 73 - 37
panda/src/cocoadisplay/cocoaGraphicsWindow.mm

@@ -39,7 +39,7 @@
 #import <AppKit/NSImage.h>
 #import <AppKit/NSImage.h>
 #import <AppKit/NSScreen.h>
 #import <AppKit/NSScreen.h>
 #import <OpenGL/OpenGL.h>
 #import <OpenGL/OpenGL.h>
-#import <Carbon/Carbon.h>
+//#import <Carbon/Carbon.h>
 
 
 TypeHandle CocoaGraphicsWindow::_type_handle;
 TypeHandle CocoaGraphicsWindow::_type_handle;
 
 
@@ -97,20 +97,35 @@ CocoaGraphicsWindow::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool CocoaGraphicsWindow::
 bool CocoaGraphicsWindow::
 move_pointer(int device, int x, int y) {
 move_pointer(int device, int x, int y) {
+  //Hack!  Will go away when we have floating-point mouse pos.
+  MouseData md = get_pointer(device);
+  if (md.get_x() == x && md.get_y() == y) {
+    return true;
+  }
+
   if (device == 0) {
   if (device == 0) {
     CGPoint point;
     CGPoint point;
     if (_properties.get_fullscreen()) {
     if (_properties.get_fullscreen()) {
-      point = CGPointMake(x, y);
+      point = CGPointMake(x, y + 1);
     } else {
     } else {
       point = CGPointMake(x + _properties.get_x_origin(),
       point = CGPointMake(x + _properties.get_x_origin(),
-                          y + _properties.get_y_origin());
+                          y + _properties.get_y_origin() + 1);
     }
     }
 
 
-    return (CGDisplayMoveCursorToPoint(_display, point) == kCGErrorSuccess);
+    // I don't know what the difference between these two methods is.
+    //if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
+    if (CGDisplayMoveCursorToPoint(_display, point) == kCGErrorSuccess) {
+      // Generate a mouse event.
+      NSPoint pos = [_window mouseLocationOutsideOfEventStream];
+      NSPoint loc = [_view convertPoint:pos fromView:nil];
+      BOOL inside = [_view mouse:loc inRect:[_view bounds]];
+      handle_mouse_moved_event(inside, loc.x, loc.y, true);
+      return true;
+    }
   } else {
   } else {
     // No support for raw mice at the moment.
     // No support for raw mice at the moment.
-    return false;
   }
   }
+  return false;
 }
 }
 
 
 
 
@@ -145,13 +160,16 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     // Fullscreen.
     // Fullscreen.
     [cocoagsg->_context setFullScreen];
     [cocoagsg->_context setFullScreen];
   } else {
   } else {
-    nassertr([_view lockFocusIfCanDraw], false);
     // Although not recommended, it is technically possible to
     // Although not recommended, it is technically possible to
     // use the same context with multiple different-sized windows.
     // use the same context with multiple different-sized windows.
     // If that happens, the context needs to be updated accordingly.
     // If that happens, the context needs to be updated accordingly.
     if ([cocoagsg->_context view] != _view) {
     if ([cocoagsg->_context view] != _view) {
+      //XXX I'm not 100% sure that changing the view requires it to update.
       _context_needs_update = true;
       _context_needs_update = true;
       [cocoagsg->_context setView:_view];
       [cocoagsg->_context setView:_view];
+
+      cocoadisplay_cat.spam()
+        << "Switching context to view " << _view << "\n";
     }
     }
   }
   }
 
 
@@ -161,6 +179,11 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     _context_needs_update = false;
     _context_needs_update = false;
   }
   }
 
 
+  // Lock the view for drawing.
+  if (!_properties.get_fullscreen()) {
+    nassertr([_view lockFocusIfCanDraw], false);
+  }
+
   // Make the context current.
   // Make the context current.
   [cocoagsg->_context makeCurrentContext];
   [cocoagsg->_context makeCurrentContext];
 
 
@@ -191,6 +214,15 @@ end_frame(FrameMode mode, Thread *current_thread) {
   end_frame_spam(mode);
   end_frame_spam(mode);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
 
+  if (!_properties.get_fullscreen()) {
+    [_view unlockFocus];
+  }
+  // Release the context.
+  CocoaGraphicsStateGuardian *cocoagsg;
+  DCAST_INTO_V(cocoagsg, _gsg);
+  
+  CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
+
   if (mode == FM_render) {
   if (mode == FM_render) {
     // end_render_texture();
     // end_render_texture();
     copy_to_textures();
     copy_to_textures();
@@ -221,12 +253,14 @@ end_flip() {
     CocoaGraphicsStateGuardian *cocoagsg;
     CocoaGraphicsStateGuardian *cocoagsg;
     DCAST_INTO_V(cocoagsg, _gsg);
     DCAST_INTO_V(cocoagsg, _gsg);
 
 
+    CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
+
+    // Swap the front and back buffer.
     [cocoagsg->_context flushBuffer];
     [cocoagsg->_context flushBuffer];
-    if (!_properties.get_fullscreen()) {
-      [_view unlockFocus];
-    }
 
 
-    // Release the context.
+    // Flush the window
+    [[_view window] flushWindow];
+
     CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
     CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]);
   }
   }
   GraphicsWindow::end_flip();
   GraphicsWindow::end_flip();
@@ -247,15 +281,14 @@ process_events() {
   GraphicsWindow::process_events();
   GraphicsWindow::process_events();
 
 
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
   NSEvent *event = nil;
   NSEvent *event = nil;
 
 
   while (true) {
   while (true) {
     event = [NSApp
     event = [NSApp
-      nextEventMatchingMask: NSAnyEventMask
-      untilDate: nil
-      inMode: NSDefaultRunLoopMode
-      dequeue: YES];
+      nextEventMatchingMask:NSAnyEventMask
+      untilDate:nil
+      inMode:NSDefaultRunLoopMode
+      dequeue:YES];
 
 
     if (event == nil) {
     if (event == nil) {
       break;
       break;
@@ -288,7 +321,7 @@ open_window() {
   if (_gsg == 0) {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     // There is no old gsg.  Create a new one.
     cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, NULL);
     cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, NULL);
-    cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, true, false);
+    cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, false);
     _gsg = cocoagsg;
     _gsg = cocoagsg;
   } else {
   } else {
     // If the old gsg has the wrong pixel format, create a
     // If the old gsg has the wrong pixel format, create a
@@ -296,7 +329,7 @@ open_window() {
     DCAST_INTO_R(cocoagsg, _gsg, false);
     DCAST_INTO_R(cocoagsg, _gsg, false);
     if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) {
     if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) {
       cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, cocoagsg);
       cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, cocoagsg);
-      cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, true, false);
+      cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, false);
       _gsg = cocoagsg;
       _gsg = cocoagsg;
     }
     }
   }
   }
@@ -348,7 +381,7 @@ open_window() {
 
 
       // Depending on whether the window handle comes from a Carbon or a Cocoa
       // Depending on whether the window handle comes from a Carbon or a Cocoa
       // application, it could be either a HIViewRef or an NSView or NSWindow.
       // application, it could be either a HIViewRef or an NSView or NSWindow.
-      // Currently, we only support a Cocoa NSView, but we may in the future
+      // Currently, we only support a Cocoa NSView, but we could in the future
       // add support for Carbon parents using HICocoaView.
       // add support for Carbon parents using HICocoaView.
 
 
       if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
       if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
@@ -373,6 +406,8 @@ open_window() {
   }
   }
 
 
   // Center the window if coordinates were set to -1 or -2
   // Center the window if coordinates were set to -1 or -2
+  //TODO: perhaps in future, in the case of -1, it should use the origin
+  // used in a previous run of Panda
   NSRect container;
   NSRect container;
   if (parent_nsview != NULL) {
   if (parent_nsview != NULL) {
     container = [parent_nsview bounds];
     container = [parent_nsview bounds];
@@ -498,14 +533,14 @@ open_window() {
     [_window setShowsResizeIndicator: !_properties.get_fixed_size()];
     [_window setShowsResizeIndicator: !_properties.get_fixed_size()];
 
 
     if (_properties.get_fullscreen()) {
     if (_properties.get_fullscreen()) {
-      [_window makeKeyAndOrderFront: nil];
+      [_window makeKeyAndOrderFront:nil];
      } else if (_properties.get_minimized()) {
      } else if (_properties.get_minimized()) {
-      [_window makeKeyAndOrderFront: nil];
-      [_window miniaturize: nil];
+      [_window makeKeyAndOrderFront:nil];
+      [_window miniaturize:nil];
     } else if (_properties.get_foreground()) {
     } else if (_properties.get_foreground()) {
-      [_window makeKeyAndOrderFront: nil];
+      [_window makeKeyAndOrderFront:nil];
     } else {
     } else {
-      [_window orderBack: nil];
+      [_window orderBack:nil];
     }
     }
 
 
     if (_properties.get_fullscreen()) {
     if (_properties.get_fullscreen()) {
@@ -547,8 +582,9 @@ open_window() {
 
 
   // Make the context current.
   // Make the context current.
   _context_needs_update = false;
   _context_needs_update = false;
-  [cocoagsg->_context update];
   [cocoagsg->_context makeCurrentContext];
   [cocoagsg->_context makeCurrentContext];
+  [cocoagsg->_context setView:_view];
+  [cocoagsg->_context update];
 
 
   cocoagsg->reset_if_new();
   cocoagsg->reset_if_new();
 
 
@@ -821,8 +857,6 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_origin();
     properties.clear_origin();
   }
   }
 
 
-  //TODO: mouse mode
-
   if (properties.has_title() && _window != nil) {
   if (properties.has_title() && _window != nil) {
     _properties.set_title(properties.get_title());
     _properties.set_title(properties.get_title());
     [_window setTitle:[NSString stringWithUTF8String:properties.get_title().c_str()]];
     [_window setTitle:[NSString stringWithUTF8String:properties.get_title().c_str()]];
@@ -1224,10 +1258,6 @@ handle_minimize_event(bool minimized) {
     return;
     return;
   }
   }
 
 
-  WindowProperties properties;
-  properties.set_minimized(minimized);
-  system_changed_properties(properties);
-
   if (cocoadisplay_cat.is_debug()) {
   if (cocoadisplay_cat.is_debug()) {
     if (minimized) {
     if (minimized) {
       cocoadisplay_cat.debug() << "Window was miniaturized\n";
       cocoadisplay_cat.debug() << "Window was miniaturized\n";
@@ -1235,6 +1265,10 @@ handle_minimize_event(bool minimized) {
       cocoadisplay_cat.debug() << "Window was deminiaturized\n";
       cocoadisplay_cat.debug() << "Window was deminiaturized\n";
     }
     }
   }
   }
+
+  WindowProperties properties;
+  properties.set_minimized(minimized);
+  system_changed_properties(properties);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1245,10 +1279,6 @@ handle_minimize_event(bool minimized) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CocoaGraphicsWindow::
 void CocoaGraphicsWindow::
 handle_foreground_event(bool foreground) {
 handle_foreground_event(bool foreground) {
-  WindowProperties properties;
-  properties.set_foreground(foreground);
-  system_changed_properties(properties);
-
   if (cocoadisplay_cat.is_debug()) {
   if (cocoadisplay_cat.is_debug()) {
     if (foreground) {
     if (foreground) {
       cocoadisplay_cat.debug() << "Window became key\n";
       cocoadisplay_cat.debug() << "Window became key\n";
@@ -1257,6 +1287,10 @@ handle_foreground_event(bool foreground) {
     }
     }
   }
   }
 
 
+  WindowProperties properties;
+  properties.set_foreground(foreground);
+  system_changed_properties(properties);
+
   if (foreground && _properties.get_mouse_mode() != WindowProperties::M_relative) {
   if (foreground && _properties.get_mouse_mode() != WindowProperties::M_relative) {
     // The mouse position may have changed during
     // The mouse position may have changed during
     // the time that we were not the key window.
     // the time that we were not the key window.
@@ -1500,7 +1534,7 @@ handle_mouse_button_event(int button, bool down) {
 //               Should only be called by CocoaPandaView.
 //               Should only be called by CocoaPandaView.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CocoaGraphicsWindow::
 void CocoaGraphicsWindow::
-handle_mouse_moved_event(bool in_window, int x, int y, bool absolute) {
+handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
   if (absolute) {
   if (absolute) {
     if (cocoadisplay_cat.is_spam()) {
     if (cocoadisplay_cat.is_spam()) {
       if (in_window != _input_devices[0].get_pointer().get_in_window()) {
       if (in_window != _input_devices[0].get_pointer().get_in_window()) {
@@ -1553,11 +1587,11 @@ handle_wheel_event(double x, double y) {
     _input_devices[0].button_up(MouseButton::wheel_down());
     _input_devices[0].button_up(MouseButton::wheel_down());
   }
   }
 
 
-  //TODO: check if this is correct
+  //TODO: check if this is correct, I don't own a MacBook
   if (x > 0.0) {
   if (x > 0.0) {
     _input_devices[0].button_down(MouseButton::wheel_right());
     _input_devices[0].button_down(MouseButton::wheel_right());
     _input_devices[0].button_up(MouseButton::wheel_right());
     _input_devices[0].button_up(MouseButton::wheel_right());
-  } else if (y < 0.0) {
+  } else if (x < 0.0) {
     _input_devices[0].button_down(MouseButton::wheel_left());
     _input_devices[0].button_down(MouseButton::wheel_left());
     _input_devices[0].button_up(MouseButton::wheel_left());
     _input_devices[0].button_up(MouseButton::wheel_left());
   }
   }
@@ -1659,6 +1693,7 @@ map_function_key(unsigned short keycode) {
   case NSUserFunctionKey:
   case NSUserFunctionKey:
   case NSSystemFunctionKey:
   case NSSystemFunctionKey:
   case NSPrintFunctionKey:
   case NSPrintFunctionKey:
+    break;
   case NSClearLineFunctionKey:
   case NSClearLineFunctionKey:
     return KeyboardButton::num_lock();
     return KeyboardButton::num_lock();
   case NSClearDisplayFunctionKey:
   case NSClearDisplayFunctionKey:
@@ -1673,6 +1708,7 @@ map_function_key(unsigned short keycode) {
   case NSUndoFunctionKey:
   case NSUndoFunctionKey:
   case NSRedoFunctionKey:
   case NSRedoFunctionKey:
   case NSFindFunctionKey:
   case NSFindFunctionKey:
+    break;
   case NSHelpFunctionKey:
   case NSHelpFunctionKey:
     return KeyboardButton::help();
     return KeyboardButton::help();
   case NSModeSwitchFunctionKey:
   case NSModeSwitchFunctionKey:

+ 5 - 0
panda/src/cocoadisplay/cocoaPandaView.h

@@ -23,8 +23,13 @@ class CocoaGraphicsWindow;
 }
 }
 
 
 - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window;
 - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window;
+- (NSOpenGLContext*) openGLContext;
+- (GraphicsWindow*) graphicsWindow;
+
+- (void) drawRect:(NSRect)dirtyRect;
 - (void) finalize;
 - (void) finalize;
 - (BOOL) isFlipped;
 - (BOOL) isFlipped;
+- (BOOL) needsDisplay;
 - (BOOL) acceptsFirstResponder;
 - (BOOL) acceptsFirstResponder;
 - (BOOL) becomeFirstResponder;
 - (BOOL) becomeFirstResponder;
 - (BOOL) resignFirstResponder;
 - (BOOL) resignFirstResponder;

+ 25 - 3
panda/src/cocoadisplay/cocoaPandaView.mm

@@ -21,6 +21,9 @@
 - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window {
 - (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window {
   self = [super initWithFrame: frameRect];
   self = [super initWithFrame: frameRect];
 
 
+  _context = context;
+  [self setCanDrawConcurrently:YES];
+
   cocoadisplay_cat.debug()
   cocoadisplay_cat.debug()
     << "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n";
     << "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n";
   _graphicsWindow = window;
   _graphicsWindow = window;
@@ -28,6 +31,21 @@
   return self;
   return self;
 }
 }
 
 
+- (NSOpenGLContext*) openGLContext {
+  return _context;
+}
+
+- (GraphicsWindow*) graphicsWindow {
+  return _graphicsWindow;
+}
+
+- (void) drawRect:(NSRect)dirtyRect {
+  // Do nothing.  We draw from another thread.
+
+  cocoadisplay_cat.spam()
+    << "drawRect was called.\n";
+}
+
 - (void) finalize {
 - (void) finalize {
   _graphicsWindow->handle_close_event();
   _graphicsWindow->handle_close_event();
   [super finalize];
   [super finalize];
@@ -39,6 +57,11 @@
   return YES;
   return YES;
 }
 }
 
 
+- (BOOL) needsDisplay {
+  // Never, we don't use drawRect.  We draw from elsewhere.
+  return NO;
+}
+
 - (BOOL) acceptsFirstResponder {
 - (BOOL) acceptsFirstResponder {
   return YES;
   return YES;
 }
 }
@@ -59,7 +82,6 @@
 
 
 - (void) setFrame: (NSRect) frame {
 - (void) setFrame: (NSRect) frame {
   [super setFrame: frame];
   [super setFrame: frame];
-  //[_context update];
   //_graphicsWindow->handle_resize_event();
   //_graphicsWindow->handle_resize_event();
 }
 }
 
 
@@ -111,7 +133,7 @@
 }
 }
 
 
 - (void) otherMouseDown: (NSEvent *) event {
 - (void) otherMouseDown: (NSEvent *) event {
-  // 2 and 3 are swapped, for consistency with X11 implementation
+  // 1 and 2 are swapped, for consistency with X11 implementation
   if ([event buttonNumber] == 2) {
   if ([event buttonNumber] == 2) {
     _graphicsWindow->handle_mouse_button_event(1, true);
     _graphicsWindow->handle_mouse_button_event(1, true);
   } else {
   } else {
@@ -124,7 +146,7 @@
 }
 }
 
 
 - (void) otherMouseUp: (NSEvent *) event {
 - (void) otherMouseUp: (NSEvent *) event {
-  // 2 and 3 are swapped, for consistency with X11 implementation
+  // 1 and 2 are swapped, for consistency with X11 implementation
   if ([event buttonNumber] == 2) {
   if ([event buttonNumber] == 2) {
     _graphicsWindow->handle_mouse_button_event(1, false);
     _graphicsWindow->handle_mouse_button_event(1, false);
   } else {
   } else {

+ 1 - 0
panda/src/cocoadisplay/cocoaPandaWindow.mm

@@ -29,6 +29,7 @@
     [self setDelegate:delegate];
     [self setDelegate:delegate];
     [self setOpaque:YES];
     [self setOpaque:YES];
     [self setReleasedWhenClosed:YES];
     [self setReleasedWhenClosed:YES];
+    [self setAllowsConcurrentViewDrawing:YES];
 
 
     // Necessary to be able to accept mouseMoved in the NSView
     // Necessary to be able to accept mouseMoved in the NSView
     [self setAcceptsMouseMovedEvents:YES];
     [self setAcceptsMouseMovedEvents:YES];