[FIXED] Adopt new JAWT API on Mac OS X so that Plugin2 will work.

Started by bino_george, June 13, 2011, 18:49:15

Previous topic - Next topic

bino_george

As of Java for Mac OS X 10.6 Update 4 and 10.5 Update 9 there is an addition to the JAWT API that enables 3rd party 3D technologies in applets outside of the browser process (Plugin2). More info at :

http://developer.apple.com/library/mac/#releasenotes/Java/JavaSnowLeopardUpdate4LeopardUpdate9RN/NewandNoteworthy/NewandNoteworthy.html

The JAWT example at : http://developer.apple.com/library/mac/#samplecode/JAWTExample/Introduction/Intro.html has been modified to show how to use this new API.

Please adopt this mechanism so that LWJGL can work in browsers that support only Plugin2 such as Chrome and FireFox 4.

P.S. The latest developer preview of Java for Mac OS X (10M3418+9M3418) at https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=20809 has some important fixes in this area, so please be sure to update to this version.

kappa

oh cool, thx for posting this.

I actually tried to implement this on the weekend, almost got it working but ran into a issue.

LWJGL on mac currently works by creating its own NSOpenGLContext and NSOpenGLPixelFormat. The NSView of a Java Canvas is obtained allowing the OpenGL content to be rendered on it.

To move over to the new API, I implemented a custom NSOpenGLLayer which uses the above created NSOpenGLContext and NSOpenGLPixelFormat.

The problem however is that it only worked if OpenGL calls are made inside the method drawInOpenGLContext of the custom NSOpenGLLayer. Since LWJGL users manage their own game loop in Java and calling any opengl calls from java maps directly onto the native OpenGL calls. There doesn't seem to a be a way to easily structure LWJGL so that the calls fall into the drawInOpenGLContext method.

Any ideas if there is a way to render directly to the NSOpenGLContext like its done currently with a NSView and still display it in a NSOpenGLLayer? or is there some other method you can suggest?

Thanks

Kappa

swingler

I don't believe we have a good answer at this time. It might be worth asking on a CoreAnimation and/or OpenGL mailing list at Apple what the best approach might be.

It's possible that a proxy OpenGL context will have to be created that records all the instructions that come in from the Java thread, and then dispatches them when it is pumped from the main thread by -drawInOpenGLContext. Does that even sound feasible?

kappa

hmm, proxy context could work will give it a try, however there are a few use cases that it wouldn't work for. Will see if I can find a proper solution (or if anyone has any good ideas?) but in the mean time if you do come up with something do let us know. It'd be really nice to finally get opengl applets working properly on mac, the tech has so much potential.

Matzon

afaik, we would have to set a flag/lock of some sorts, so it doesn't start to process the queue while in the middle of a glbegin/glend or similar.
furthermore, we would have to do all of this behind the scenes because of a macosx only limitation :/

Momoko_Fan

I suppose that just for this we could have some kind of callback function defined in the Display class that would get called in that native method?
What thread is that "drawInOpenGLContext" function called in?

kappa

Quote from: Momoko_Fan on June 18, 2011, 00:10:37
I suppose that just for this we could have some kind of callback function defined in the Display class that would get called in that native method?
Yeh spasi mentioned that we can do something like this with AWTGLCanvas since all GL calls have to be in the initGL() and paintGL() methods, so we can call those methods from the native thread.

Quote from: Momoko_Fan on June 18, 2011, 00:10:37
What thread is that "drawInOpenGLContext" function called in?
Its part of the Cocoa NSOpenGLLayer on the native side probably on some Cocoa thread.

Still be nice to get it working with the standard Display.setParent(), gonna experiment with some thread locking/unlocking to see if we can somehow hold the native drawInOpenGLContext method open until all the java opengl calls are made and Display.update() called, then put the java thread to sleep in the Display.update() method until the native code returns to the drawInOpenGLContext method. Probably not a good idea but worth a try.

pjohnsen

Trying to take a look at this. However I'm getting errors building the JAWT sample with latest xcode on 10.7:
PBXCp build/Debug/JAWTExample.jar /Users/pelle/Library/Developer/Xcode/DerivedData/JAWTExample-enilygmyiqhmheggzfkcgjfwatdm/Build/Products/Debug/JAWTExample.app/Contents/Resources/Java/JAWTExample.jar
    cd /Users/pelle/Downloads/JAWTExample
    builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git -resolve-src-symlinks /Users/pelle/Downloads/JAWTExample/build/Debug/JAWTExample.jar /Users/pelle/Library/Developer/Xcode/DerivedData/JAWTExample-enilygmyiqhmheggzfkcgjfwatdm/Build/Products/Debug/JAWTExample.app/Contents/Resources/Java

error: /Users/pelle/Downloads/JAWTExample/build/Debug/JAWTExample.jar: No such file or directory


Looks like it's trying to copy it from the wrong place. I fixed this by changing the dst part of the ant file to:
<condition property="dst" value="build/${env.CONFIGURATION}">
		<isset property="env.CONFIGURATION"/>
	</condition>



pjohnsen

Filed bugreport with apple: https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/29/wo/cv1Re01Jb2kytFJmbbnLlM/9.66

This is what I currently have in MacOSXCanvasPeerInfo, but it crashes at: surfaceLayers.layer = caGLLayer :(


JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXCanvasPeerInfo_nInitHandle
 (JNIEnv *env, jclass clazz, jobject lock_buffer_handle, jobject peer_info_handle) {
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle);
   AWTSurfaceLock *surface = (AWTSurfaceLock *)(*env)->GetDirectBufferAddress(env, lock_buffer_handle);
   JAWT_MacOSXDrawingSurfaceInfo *macosx_dsi = (JAWT_MacOSXDrawingSurfaceInfo *)surface->dsi->platformInfo;

     NSLog(@"start: %08x", macosx_dsi);
     
     [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
         NSLog(@"dsi: %08x", surface->dsi);
         // attach the "root layer" to the AWT Canvas surface layers
         id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)surface->dsi->platformInfo;
         NSLog(@"surfaceLayers: %08x", surfaceLayers);
         NSLog(@"new gl layer");
         RotatingSquareGLLayer *caGLLayer = [[RotatingSquareGLLayer new] autorelease];
         //caGLLayer.asynchronous = YES;
         NSLog(@"set gl layer: %@", caGLLayer);
         surfaceLayers.layer = caGLLayer;
         NSLog(@"main thread done");
     }];
     
     NSLog(@"release pool");
     
     
   peer_info->nsview = macosx_dsi->cocoaViewRef;
   peer_info->window = true;

   [pool release];
}

pjohnsen

I've had some progress, and am now able to show the NSGLLayer from the sample in lwjgl applet: http://dev.pellej.com/lwjgl/applet/basic/basicapplet.html

Gonna work on getting lwjgl to use pbuffer which is then rendered by NSGLLayer

pjohnsen


kappa

awesome work, looking forward to getting this into lwjgl.

pjohnsen

I updated the patch on http://codereview.appspot.com/4961050/:

  • Cleaned up drawing of pbuffer (don't clear, use drawarrays)
  • Added checks for CALayer support

kappa

By way of update the above patch was committed, however nightly build server broke as a result (oops ;D). From the exception it seems the new api added in the recent Apple Java SDK's was not found, likely because the server has an older version of the java sdk installed, hopefully Endolf will have a look at this soon.

kappa

I can confirm that this issue should hopefully now be fixed in the latest nightly builds of LWJGL, please do test and report any issues that you may have so that they can be ironed out by the LWJGL 2.8 release.