Performance: OSX version still mind numbingly slow

Something wacky is going on with the OSX version of JOGL because it is a LOT slower (several orders) than it should be. I know that in the past Apple has had some issue with certain pixel depths and such, but unless the port is just doing something wacky I would imagine that at most the OSX component is getting a rendering component from the AWT component and rendering directly into it - something that absolutely should not be taking anywhere near as long as its taking. Something that runs at a rate such that I cannot even make it on on Windows is literally crawling on OSX through JOGL - and runs at a reasonable speec in pure C++ on 10.3. Something is terribly wrong here.

Okay, I’m going stop and actually take a look at this and start asking some questions as I’m not really hearing anything from anyone yet.

I’ve pulled down the source tree for the OSX port and started taking a look around. Right now I’m in MacOSXOnscreenGLContext.java. I saw some hardcoded stuff for the rendering context for 32 bit color, 24 bit depth, and 8 bit stencil (ouch).


  GLuint attribs[] = {
    NSOpenGLPFANoRecovery,
    NSOpenGLPFAWindow,
    NSOpenGLPFAAccelerated,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFAColorSize, 32,
    NSOpenGLPFAAlphaSize, 8,
    NSOpenGLPFADepthSize, 24,
    NSOpenGLPFAStencilSize, 8,
    NSOpenGLPFAAccumSize, 0,
    0
  };


  protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
    try {
      if (!lockSurface()) {
        return false;
      }
            
      boolean created = false;
      if (nsContext == 0) {
        create();
        if (DEBUG) {
          System.err.println("!!! Created GL nsContext for " + getClass().getName());
        }
        created = true;
      }
            
      if (!CGL.makeCurrentContext(nsView, nsContext)) {
        throw new GLException("Error making nsContext current");
      }
            
      if (created) {
        resetGLFunctionAvailability();
        if (initAction != null) {
          initAction.run();
        }
      }
      return true;
    } catch (RuntimeException e) {
      try {
        unlockSurface();
      } catch (Exception e2) {
        // do nothing if unlockSurface throws
      }
            
      throw(e); 
    }
  }

Okay I’m starting to see some scary stuff in the OSX code that looks very unfamiliar for regular OpenGL programs and doesn’t exist in other ports.

  1. What is resetGLFunctionAvailability and why is it being called every makeCurrent().

  2. Why is initAction.run() being called here? Or more appropriately - why is makeCurrent taking a runnable at all?

Even scarier here. Assuming CGL.flushBuffer is doing what it looks like its doing, why isn’t it just calling swapBuffers instead of flushing them and stalling the pipeline?

[quote]1) What is resetGLFunctionAvailability and why is it being called every makeCurrent().

  1. Why is initAction.run() being called here? Or more appropriately - why is makeCurrent taking a runnable at all?

Even scarier here. Assuming CGL.flushBuffer is doing what it looks like its doing, why isn’t it just calling swapBuffers instead of flushing them and stalling the pipeline?
[/quote]
I don’t know anything about the code, but from just what you have posted it seems that the intention is NOT to do 1 & 2 for every call to makeCurrent()… only when nsContext == 0 and therefore create() is called and perhaps a debug message is printed will it call those other init things, because then created == true.

It looks like nsContext is not supposed to be 0 EVERY time through that function… is that what you are seeing?

Okay… first up - CGL for OSX isn’t defined in the same code path as X11 and WGL and that needs to change from a maintainability perspective.

Next up


  /** Entry point to C language function: 
 <code> Bool flushBuffer(void *  nsView, void *  nsContext); </code>    */
  static public native boolean flushBuffer(long nsView, long nsContext);

How can one find out what the implementation of flushBuffer is in OpenGL terms?

EDIT - Okay flushBuffer is the reasonable equivalent to SwapBuffers on Windows.

You are correct. I didn’t originally see the nsContext - CGL.createContext().

EDIT- I have started to focus my search on the setup of the GLContext as my search seems to suggest that my application may not be running in hardware at all. There should normally be a way to tell these things and I file an RFE so that we can tell.

On the positive side, when we do finally want to go fullscreen - the Cocoa interface makes that childishly simple.

[quote]Okay… first up - CGL for OSX isn’t defined in the same code path as X11 and WGL and that needs to change from a maintainability perspective.
[/quote]
It may be a little confusing, but there are two WGL and GLX classes. The public ones expose the window system-specific vendor extensions. This has only been done because we thought it might be useful, not because there were any particular extensions we had in mind for the end user to access. They might as well be hidden from public view. There are also JOGL implementation-internal WGL and GLX classes which define the APIs needed to create and bind OpenGL contexts. These have deliberately been excluded from the public API.

On Mac OS X it wasn’t clear that there were any window system-specific extensions to go into an analogous CGL class so there are no useful methods defined in that class. The internal CGL class, which defines the methods needed to create and manage OpenGL contexts, is in the same relative place as the internal WGL and GLX classes, namely net.java.games.jogl.impl.(operating system).

See http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSOpenGLContext.html#//apple_ref/doc/uid/20000463/CJBBIAGG

What I found when I checked out of CVS was that build/gensrc/classes/net/java/games/jogl contained the WGL and GLX classes and then there is an impl/ directory with a single subdirectory /macosx (no other platforms have anything here).

Removing the 8 bit stencil has helped performance tremendously - but things are still slower than I expect them to be. The hunt continues (albeit slower as I now have something close to reasonable performance). I also pulled out a couple of the flags that didn’t really have purpose in the NSOpenGLPixelFormat. I’ve reduced them to what I was using, but this piece needs to become configurable from the application and not be hardcoded as it is now:


  GLuint attribs[] = {
    NSOpenGLPFAWindow,
    NSOpenGLPFAAccelerated,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFAColorSize, 32,
    0
  };

This section is likely the source of my problems as its requesting a lot of features that I’m not on any other platform and that is probably accounting for the performance difference - though I cannot confirm that yet.

Glad that you’re tracking this down – please fix the code properly, though, and look at the GLCapabilities when choosing what to put in to the attributes array. Also please send it to me for review when it’s done.

The impl directory under build/gensrc/classes only ever contains one directory on any given platform since the Java code implementing each window system’s interface doesn’t compile on all platforms. However, if the empty CGL interface is missing from the jogl directory under build/gensrc/classes on Mac OS X after building then that is a bug in the build process and you should file an issue.

[quote]Glad that you’re tracking this down – please fix the code properly, though, and look at the GLCapabilities when choosing what to put in to the attributes array. Also please send it to me for review when it’s done.
[/quote]
I feel like I’m a Jr. Developer again :wink: