Skip to content

Commit

Permalink
OSX/CALayer Threading Part4: Stream all JAWT Root CALayer Operations …
Browse files Browse the repository at this point in the history
…on OSX Main-Thread

Previous code created, set and unset the root CALayer on the current thread,
which lead to a very delayed destruction of the root CALayer w/.
With Java7 this lead to a possible resource starvation in certain situations,
since Java7 uses an CAOpenGLLayer.

Similar w/  f354fb2,
creation, set and unset is operated on main-thread.
  • Loading branch information
sgothel committed Apr 4, 2013
1 parent 15e2095 commit 68526d3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 120 deletions.
24 changes: 12 additions & 12 deletions src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,29 @@ @implementation MyNSOpenGLContext

- (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share
{
DBG_PRINT("MyNSOpenGLContext.initWithFormat.0: format %p, share %p\n", format, share);
DBG_PRINT("MyNSOpenGLContext::initWithFormat.0: format %p, share %p\n", format, share);
MyNSOpenGLContext * o = [super initWithFormat:format shareContext:share];
DBG_PRINT("MyNSOpenGLContext.initWithFormat.X: new %p\n", o);
DBG_PRINT("MyNSOpenGLContext::initWithFormat.X: new %p\n", o);
return o;
}

- (void)setView:(NSView *)view
{
DBG_PRINT("MyNSOpenGLContext.setView: this.0 %p, view %p\n", self, view);
DBG_PRINT("MyNSOpenGLContext::setView: this.0 %p, view %p\n", self, view);
// NSLog(@"MyNSOpenGLContext::setView: %@",[NSThread callStackSymbols]);
if(NULL != view) {
[super setView:view];
} else {
[self clearDrawable];
}
DBG_PRINT("MyNSOpenGLContext.setView.X\n");
DBG_PRINT("MyNSOpenGLContext::setView.X\n");
}

- (void)update
{
DBG_PRINT("MyNSOpenGLContext.update: this.0 %p, view %p\n", self, [self view]);
DBG_PRINT("MyNSOpenGLContext::update: this.0 %p, view %p\n", self, [self view]);
[super update];
DBG_PRINT("MyNSOpenGLContext.update.X\n");
DBG_PRINT("MyNSOpenGLContext::update.X\n");
}

#ifdef DBG_LIFECYCLE
Expand Down Expand Up @@ -132,20 +132,20 @@ - (void)dealloc
// NSLog(@"MyNSOpenGLContext::dealloc: %@",[NSThread callStackSymbols]);

[self clearDrawable];
DBG_PRINT("MyNSOpenGLContext.dealloc.1 %d\n", CGLRETAINCOUNT(cglCtx));
DBG_PRINT("MyNSOpenGLContext::dealloc.1 %d\n", CGLRETAINCOUNT(cglCtx));
if( NULL != cglCtx ) {
CGLRetainContext( cglCtx );
DBG_PRINT("MyNSOpenGLContext.dealloc.2 %d\n", CGLRETAINCOUNT(cglCtx));
DBG_PRINT("MyNSOpenGLContext::dealloc.2 %d\n", CGLRETAINCOUNT(cglCtx));
}
[super dealloc];
DBG_PRINT("MyNSOpenGLContext.dealloc.3 %d\n", CGLRETAINCOUNT(cglCtx));
DBG_PRINT("MyNSOpenGLContext::dealloc.3 %d\n", CGLRETAINCOUNT(cglCtx));
if( NULL != cglCtx ) {
CGLReleaseContext( cglCtx );
DBG_PRINT("MyNSOpenGLContext.dealloc.4 %d\n", CGLRETAINCOUNT(cglCtx));
DBG_PRINT("MyNSOpenGLContext::dealloc.4 %d\n", CGLRETAINCOUNT(cglCtx));
CGLDestroyContext( cglCtx );
DBG_PRINT("MyNSOpenGLContext.dealloc.5 %d\n", CGLRETAINCOUNT(cglCtx));
DBG_PRINT("MyNSOpenGLContext::dealloc.5 %d\n", CGLRETAINCOUNT(cglCtx));
}
DBG_PRINT("MyNSOpenGLContext.dealloc.X\n");
DBG_PRINT("MyNSOpenGLContext::dealloc.X\n");
}

@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,46 +85,28 @@ protected void invalidateNative() {
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
}
if(0 != rootSurfaceLayer) {
final JAWT jawt = getJAWT();
if( null != jawt ) {
final JAWT_DrawingSurface ds = jawt.GetDrawingSurface(component);
if (ds != null) {
if ( 0 == ( ds.Lock() & JAWTFactory.JAWT_LOCK_ERROR ) ) {
JAWT_DrawingSurfaceInfo dsi = null;
try {
dsi = ds.GetDrawingSurfaceInfo();
try {
UnsetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayer);
} catch (Exception e) {
System.err.println("Error clearing JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer));
e.printStackTrace();
}
} finally {
if ( null != dsi ) {
ds.FreeDrawingSurfaceInfo(dsi);
}
ds.Unlock();
}
OSXUtil.RunOnMainThread(false, new Runnable() {
public void run() {
if( 0 != rootSurfaceLayer ) {
if( 0 != jawtSurfaceLayersHandle) {
UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
}
jawt.FreeDrawingSurface(ds);
}
}

OSXUtil.RunOnMainThread(false, new Runnable() {
public void run() {
OSXUtil.DestroyCALayer(rootSurfaceLayer, false);
OSXUtil.DestroyCALayer(rootSurfaceLayer);
rootSurfaceLayer = 0;
}
});
}
jawtSurfaceLayersHandle = 0;
}
});
}
windowHandle=0;
}

@Override
protected void attachSurfaceLayerImpl(final long layerHandle) {
OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, getWidth(), getHeight());
OSXUtil.RunOnMainThread(false, new Runnable() {
public void run() {
OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, getWidth(), getHeight());
} } );
}

@Override
Expand All @@ -139,11 +121,8 @@ protected void layoutSurfaceLayerImpl(long layerHandle, int width, int height) {
protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
OSXUtil.RunOnMainThread(false, new Runnable() {
public void run() {
final long l = MacOSXJAWTWindow.this.getAttachedSurfaceLayer();
if( 0 != l ) {
detachNotify.run();
OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle, false);
}
detachNotify.run();
OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle);
} } );
}

Expand Down Expand Up @@ -256,24 +235,32 @@ public Object run() {
}
}
if(null == errMsg) {
if(0 == rootSurfaceLayer) {
rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
if(0 == rootSurfaceLayer) {
errMsg = "Could not create root CALayer";
} else {
try {
SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayer);
} catch(Exception e) {
errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer)+", cause: "+e.getMessage();
jawtSurfaceLayersHandle = GetJAWTSurfaceLayersHandle0(dsi.getBuffer());
OSXUtil.RunOnMainThread(false, new Runnable() {
public void run() {
String errMsg = null;
if(0 == rootSurfaceLayer && 0 != jawtSurfaceLayersHandle) {
rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
if(0 == rootSurfaceLayer) {
errMsg = "Could not create root CALayer";
} else {
try {
SetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
} catch(Exception e) {
errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer)+", cause: "+e.getMessage();
}
}
if(null != errMsg) {
if(0 != rootSurfaceLayer) {
OSXUtil.DestroyCALayer(rootSurfaceLayer);
rootSurfaceLayer = 0;
}
throw new NativeWindowException(errMsg+": "+MacOSXJAWTWindow.this);
}
}
}
}
} } );
}
if(null != errMsg) {
if(0 != rootSurfaceLayer) {
OSXUtil.DestroyCALayer(rootSurfaceLayer, true);
rootSurfaceLayer = 0;
}
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
windowHandle = 0;
Expand Down Expand Up @@ -326,20 +313,24 @@ public Point getLocationOnScreen(Point storage) {
}
protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; }


private static native long GetJAWTSurfaceLayersHandle0(Buffer jawtDrawingSurfaceInfoBuffer);

/**
* Set the given root CALayer in the JAWT surface
*/
private static native void SetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
private static native void SetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);

/**
* Unset the given root CALayer in the JAWT surface, passing the NIO DrawingSurfaceInfo buffer
*/
private static native void UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
private static native void UnsetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);

// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
private boolean dsLocked;
private JAWT_DrawingSurfaceInfo dsi;
private long jawtSurfaceLayersHandle;

private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;

Expand Down
50 changes: 14 additions & 36 deletions src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public static long GetNSWindow(long nsView) {

/**
* Create a CALayer suitable to act as a root CALayer.
* @see #DestroyCALayer(long, boolean)
* @see #DestroyCALayer(long)
* @see #AddCASublayer(long, long)
*/
public static long CreateCALayer(final int x, final int y, final int width, final int height) {
Expand All @@ -150,7 +150,7 @@ public static long CreateCALayer(final int x, final int y, final int width, fina
}

/**
* Attach a sub CALayer to the root CALayer on the main-thread w/o blocking.
* Attach a sub CALayer to the root CALayer
* <p>
* Method will trigger a <code>display</code>
* call to the CALayer hierarchy to enforce resource creation if required, e.g. an NSOpenGLContext.
Expand All @@ -166,14 +166,10 @@ public static void AddCASublayer(final long rootCALayer, final long subCALayer,
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
RunOnMainThread(false, new Runnable() {
public void run() {
if(DEBUG) {
System.err.println("OSXUtil.AttachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
}
AddCASublayer0(rootCALayer, subCALayer, width, height);
}
});
if(DEBUG) {
System.err.println("OSXUtil.AttachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
}
AddCASublayer0(rootCALayer, subCALayer, width, height);
}

/**
Expand Down Expand Up @@ -201,47 +197,29 @@ public static void FixCALayerLayout(final long rootCALayer, final long subCALaye

/**
* Detach a sub CALayer from the root CALayer.
* @param onMainThread if <code>true</code> method will be performed on the main-thread w/o blocking.
*/
public static void RemoveCASublayer(final long rootCALayer, final long subCALayer, boolean onMainThread) {
public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
final Runnable action = new Runnable() {
public void run() {
if(DEBUG) {
System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
}
RemoveCASublayer0(rootCALayer, subCALayer);
} };
if( onMainThread ) {
RunOnMainThread(false, action);
} else {
action.run();
if(DEBUG) {
System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
}
RemoveCASublayer0(rootCALayer, subCALayer);
}

/**
* Destroy a CALayer.
* @param onMainThread if <code>true</code> method will be performed on the main-thread w/o blocking.
* @see #CreateCALayer(int, int, int, int)
*/
public static void DestroyCALayer(final long caLayer, boolean onMainThread) {
public static void DestroyCALayer(final long caLayer) {
if(0==caLayer) {
throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
}
final Runnable action = new Runnable() {
public void run() {
if(DEBUG) {
System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
}
DestroyCALayer0(caLayer);
} };
if( onMainThread ) {
RunOnMainThread(false, action);
} else {
action.run();
if(DEBUG) {
System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
}
DestroyCALayer0(caLayer);
}

/**
Expand Down
44 changes: 25 additions & 19 deletions src/nativewindow/native/macosx/OSXmisc.m
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,9 @@ @implementation MyCALayer

- (id)init
{
DBG_PRINT("MyCALayer.0\n");
DBG_PRINT("MyCALayer::init.0\n");
MyCALayer * o = [super init];
DBG_PRINT("MyNSOpenGLContext.init.X: new %p\n", o);
DBG_PRINT("MyCALayer.0\n");
DBG_PRINT("MyCALayer::init.X: new %p\n", o);
return o;
}

Expand Down Expand Up @@ -593,27 +592,39 @@ static void FixCALayerLayout0(MyCALayer* rootLayer, CALayer* subLayer, jint widt
DBG_PRINT("CALayer::DestroyCALayer0.X: root %p\n", layer);
}

/*
* Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
* Method: GetJAWTSurfaceLayersHandle0
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_GetJAWTSurfaceLayersHandle0
(JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer)
{
JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
if (NULL == dsi) {
NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
return 0;
}
id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
return (jlong) ((intptr_t) surfaceLayers);
}

/*
* Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
* Method: SetJAWTRootSurfaceLayer0
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
(JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
(JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
if (NULL == dsi) {
NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
return;
}
id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]);
DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", [surfaceLayers layer], layer, (int)[layer retainCount]);
[surfaceLayers setLayer: [layer retain]]; // Pairs w/ Unset

[CATransaction commit];
Expand All @@ -628,21 +639,16 @@ static void FixCALayerLayout0(MyCALayer* rootLayer, CALayer* subLayer, jint widt
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
(JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
(JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
if (NULL == dsi) {
NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
return;
}
id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
if(layer != surfaceLayers.layer) {
if(layer != [surfaceLayers layer]) {
NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
return;
}
Expand Down

0 comments on commit 68526d3

Please sign in to comment.