From 7bb5885fc3a904f49e22f0c8cbf747d9b189a7ba Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 25 Jul 2012 04:23:35 +0200 Subject: SWT Update: SWT GLCanvas creates lazy when resource is ready; Create new NewtCanvasSWT allowing to parent NEWT windows natively. SWT GLCanvas creates lazy when resource is ready - Ensures drawable and context are created when size > zero and native visualID is valid. The latter is platform dependent. - Note that you cannot utilize custom GLCapabilities w/ this one, since the configurations is already realized - use NewtCanvasSWT. Create new NewtCanvasSWT allowing to parent NEWT windows natively: - Similar to NewtCanvasAWT - Allows attaching / detaching NEWT windows NewtCanvasAWT: Public setNEWTChild(..) fixed Added test cases for the above - tested on Linux, OSX and Windows w/ SWT Note: As usual for OSX, add -XstartOnFirstThread Details: - NEWT Display has new method: 'EDTUtil setEDTUtil(EDTUtil)' allowing to set a custom event dispatch utility. We use this to set our SWTEDTUtil for using NEWT w/ SWT complying w/ SWT threading constraints. --- src/newt/native/MacWindow.m | 56 +++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 30 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 01cbd80ec..bbadc9dd0 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 } DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]); + // Remove animations for child windows + if(NULL != parentWindow) { +NS_DURING + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; +NS_HANDLER +NS_ENDHANDLER + } + #ifdef VERBOSE_ON int dbgIdx = 1; #endif @@ -734,7 +743,7 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -742,11 +751,6 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - // '[mWin close]' causes a crash at exit. - // This probably happens b/c it sends events to the main loop - // but our resources are gone ?! - // However, issuing a simple release seems to work quite well. - // [mWin release]; [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; } @@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; - [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderFrontRegardless]; - // [mWin makeKeyWindow]; + [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; + [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); @@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 /* * Class: jogamp_newt_driver_macosx_MacWindow - * Method: requestFocusParent0 + * Method: resignFocus0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); NSWindow* pWin = [mWin parentWindow]; -#ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; -#endif - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); - if(NULL != pWin) { - [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [pWin makeKeyWindow]; + DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if( hasFocus ) { + if(NULL != pWin) { + // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO]; + [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + } else { + [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO]; + } } - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); + DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); [pool release]; } @@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 DBG_PRINT( "orderFront0 - window: %p (START)\n", win); - [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [win orderFrontRegardless]; + [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; DBG_PRINT( "orderFront0 - window: %p (END)\n", win); @@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); if(NULL == pWin) { - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; } else { - [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderBack: mWin]; + [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); -- cgit v1.2.3 From a694cadca4ab72481e777222f412f006f973f77e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 18 Aug 2012 14:12:54 +0200 Subject: NEWT Platform Driver: Uniform impl. class names [DisplayDriver, ScreenDriver, WindowDriver] to reduce complexity and programatic selection. --- make/build-newt.xml | 36 +- make/scripts/tests.sh | 4 +- .../media/nativewindow/NativeWindowFactory.java | 12 +- .../classes/com/jogamp/newt/util/MainThread.java | 2 +- src/newt/classes/jogamp/newt/DisplayImpl.java | 22 +- src/newt/classes/jogamp/newt/ScreenImpl.java | 28 +- src/newt/classes/jogamp/newt/WindowImpl.java | 21 +- .../jogamp/newt/driver/android/AndroidDisplay.java | 66 --- .../jogamp/newt/driver/android/AndroidScreen.java | 138 ------- .../jogamp/newt/driver/android/AndroidWindow.java | 458 --------------------- .../jogamp/newt/driver/android/DisplayDriver.java | 66 +++ .../newt/driver/android/NewtBaseActivity.java | 10 +- .../newt/driver/android/NewtVersionActivity.java | 2 +- .../jogamp/newt/driver/android/ScreenDriver.java | 138 +++++++ .../jogamp/newt/driver/android/WindowDriver.java | 458 +++++++++++++++++++++ .../classes/jogamp/newt/driver/awt/AWTCanvas.java | 1 + .../classes/jogamp/newt/driver/awt/AWTDisplay.java | 73 ---- .../classes/jogamp/newt/driver/awt/AWTScreen.java | 81 ---- .../classes/jogamp/newt/driver/awt/AWTWindow.java | 233 ----------- .../jogamp/newt/driver/awt/DisplayDriver.java | 73 ++++ .../jogamp/newt/driver/awt/ScreenDriver.java | 81 ++++ .../jogamp/newt/driver/awt/WindowDriver.java | 233 +++++++++++ .../jogamp/newt/driver/bcm/egl/Display.java | 85 ---- .../jogamp/newt/driver/bcm/egl/DisplayDriver.java | 85 ++++ .../classes/jogamp/newt/driver/bcm/egl/Screen.java | 75 ---- .../jogamp/newt/driver/bcm/egl/ScreenDriver.java | 75 ++++ .../classes/jogamp/newt/driver/bcm/egl/Window.java | 170 -------- .../jogamp/newt/driver/bcm/egl/WindowDriver.java | 170 ++++++++ .../jogamp/newt/driver/bcm/vc/iv/Display.java | 78 ---- .../newt/driver/bcm/vc/iv/DisplayDriver.java | 78 ++++ .../jogamp/newt/driver/bcm/vc/iv/Screen.java | 73 ---- .../jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java | 73 ++++ .../jogamp/newt/driver/bcm/vc/iv/Window.java | 149 ------- .../jogamp/newt/driver/bcm/vc/iv/WindowDriver.java | 149 +++++++ .../jogamp/newt/driver/intel/gdl/Display.java | 104 ----- .../newt/driver/intel/gdl/DisplayDriver.java | 105 +++++ .../jogamp/newt/driver/intel/gdl/Screen.java | 85 ---- .../jogamp/newt/driver/intel/gdl/ScreenDriver.java | 86 ++++ .../jogamp/newt/driver/intel/gdl/Window.java | 146 ------- .../jogamp/newt/driver/intel/gdl/WindowDriver.java | 147 +++++++ .../classes/jogamp/newt/driver/kd/Display.java | 77 ---- .../jogamp/newt/driver/kd/DisplayDriver.java | 77 ++++ src/newt/classes/jogamp/newt/driver/kd/Screen.java | 75 ---- .../jogamp/newt/driver/kd/ScreenDriver.java | 75 ++++ src/newt/classes/jogamp/newt/driver/kd/Window.java | 163 -------- .../jogamp/newt/driver/kd/WindowDriver.java | 163 ++++++++ .../jogamp/newt/driver/macosx/DisplayDriver.java | 88 ++++ .../jogamp/newt/driver/macosx/MacDisplay.java | 87 ---- .../jogamp/newt/driver/macosx/MacKeyUtil.java | 27 ++ .../jogamp/newt/driver/macosx/MacScreen.java | 143 ------- .../jogamp/newt/driver/macosx/MacWindow.java | 431 ------------------- .../jogamp/newt/driver/macosx/ScreenDriver.java | 143 +++++++ .../jogamp/newt/driver/macosx/WindowDriver.java | 431 +++++++++++++++++++ .../jogamp/newt/driver/windows/DisplayDriver.java | 95 +++++ .../jogamp/newt/driver/windows/ScreenDriver.java | 124 ++++++ .../jogamp/newt/driver/windows/WindowDriver.java | 311 ++++++++++++++ .../jogamp/newt/driver/windows/WindowsDisplay.java | 95 ----- .../jogamp/newt/driver/windows/WindowsScreen.java | 124 ------ .../jogamp/newt/driver/windows/WindowsWindow.java | 311 -------------- .../jogamp/newt/driver/x11/DisplayDriver.java | 171 ++++++++ .../jogamp/newt/driver/x11/ScreenDriver.java | 357 ++++++++++++++++ .../jogamp/newt/driver/x11/WindowDriver.java | 261 ++++++++++++ .../classes/jogamp/newt/driver/x11/X11Display.java | 171 -------- .../classes/jogamp/newt/driver/x11/X11Screen.java | 357 ---------------- .../classes/jogamp/newt/driver/x11/X11Window.java | 261 ------------ src/newt/native/AndroidWindow.c | 18 +- src/newt/native/IntelGDL.c | 24 +- src/newt/native/KDWindow.c | 20 +- src/newt/native/MacWindow.m | 116 +++--- src/newt/native/WindowsWindow.c | 78 ++-- src/newt/native/X11Common.h | 6 +- src/newt/native/X11Display.c | 22 +- src/newt/native/X11Screen.c | 62 +-- src/newt/native/X11Window.c | 42 +- src/newt/native/bcm_egl.c | 16 +- src/newt/native/bcm_vc_iv.c | 30 +- .../opengl/test/android/MovieSimpleActivity0.java | 6 +- .../opengl/test/android/MovieSimpleActivity1.java | 10 +- 78 files changed, 4608 insertions(+), 4629 deletions(-) delete mode 100644 src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java delete mode 100644 src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java delete mode 100644 src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java create mode 100644 src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/android/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java delete mode 100644 src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java delete mode 100644 src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java create mode 100644 src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/Display.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/Screen.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/Window.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Display.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Screen.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Window.java create mode 100644 src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java create mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java create mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java create mode 100644 src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/kd/Display.java create mode 100644 src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/kd/Screen.java create mode 100644 src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/kd/Window.java create mode 100644 src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java delete mode 100644 src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java delete mode 100644 src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java create mode 100644 src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java delete mode 100644 src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java delete mode 100644 src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java create mode 100644 src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java create mode 100644 src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java delete mode 100644 src/newt/classes/jogamp/newt/driver/x11/X11Display.java delete mode 100644 src/newt/classes/jogamp/newt/driver/x11/X11Screen.java delete mode 100644 src/newt/classes/jogamp/newt/driver/x11/X11Window.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/build-newt.xml b/make/build-newt.xml index 0a12374dd..64dccc6ac 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -670,30 +670,30 @@ - + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - + diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 5a8d596df..cccc825ee 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -247,7 +247,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestWindows01NEWT $* @@ -274,7 +274,7 @@ function testawtswt() { #testawt javax.media.opengl.awt.GLCanvas $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT $* -testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestAWTCloseX11DisplayBug565 $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextNewtAWTBug523 $* diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 94f5d753c..867d0733b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -57,22 +57,22 @@ public abstract class NativeWindowFactory { protected static final boolean DEBUG; /** OpenKODE/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}*/ - public static final String TYPE_EGL = "EGL"; + public static final String TYPE_EGL = "jogamp.newt.driver.kd"; /** Microsoft Windows type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_WINDOWS = "Windows"; + public static final String TYPE_WINDOWS = "jogamp.newt.driver.windows"; /** X11 type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_X11 = "X11"; + public static final String TYPE_X11 = "jogamp.newt.driver.x11"; /** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}*/ - public static final String TYPE_ANDROID = "ANDROID"; + public static final String TYPE_ANDROID = "jogamp.newt.driver.android"; /** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_MACOSX = "MacOSX"; + public static final String TYPE_MACOSX = "jogamp.newt.driver.macosx"; /** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_AWT = "AWT"; + public static final String TYPE_AWT = "jogamp.newt.driver.awt"; /** Generic DEFAULT type, where platform implementation don't care, as retrieved with {@link #getNativeWindowType(boolean)} */ public static final String TYPE_DEFAULT = "default"; diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index a6e2ae02b..9c2f2a0b7 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -74,7 +74,7 @@ import jogamp.newt.NEWTJNILibLoader; * * To support your NEWT Window platform, * you have to pass your main thread actions to {@link #invoke invoke(..)}, - * have a look at the {@link com.jogamp.newt.macosx.MacWindow MacWindow} implementation.
+ * have a look at the {@link jogamp.newt.driver.macosx.WindowDriver NEWT Mac OSX Window} driver implementation.
* TODO: Some hardcoded dependencies exist in this implementation, * where you have to patch this code or factor it out.

* diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index 867a1f176..bac4031f0 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -44,7 +44,6 @@ import com.jogamp.newt.util.EDTUtil; import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.NativeWindowFactory; public abstract class DisplayImpl extends Display { private static int serialno = 1; @@ -52,26 +51,9 @@ public abstract class DisplayImpl extends Display { private static Class getDisplayClass(String type) throws ClassNotFoundException { - Class displayClass = NewtFactory.getCustomClass(type, "Display"); + final Class displayClass = NewtFactory.getCustomClass(type, "DisplayDriver"); if(null==displayClass) { - if (NativeWindowFactory.TYPE_ANDROID == type) { - displayClass = Class.forName("jogamp.newt.driver.android.AndroidDisplay"); - } else if (NativeWindowFactory.TYPE_EGL == type) { - displayClass = Class.forName("jogamp.newt.driver.kd.Display"); - } else if (NativeWindowFactory.TYPE_WINDOWS == type) { - displayClass = Class.forName("jogamp.newt.driver.windows.WindowsDisplay"); - } else if (NativeWindowFactory.TYPE_MACOSX == type) { - displayClass = Class.forName("jogamp.newt.driver.macosx.MacDisplay"); - } else if (NativeWindowFactory.TYPE_X11 == type) { - displayClass = Class.forName("jogamp.newt.driver.x11.X11Display"); - } else if (NativeWindowFactory.TYPE_AWT == type) { - displayClass = Class.forName("jogamp.newt.driver.awt.AWTDisplay"); - } else { - throw new RuntimeException("Unknown display type \"" + type + "\""); - } - } - if(null==displayClass) { - throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".Display>"); + throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".DisplayDriver>"); } return displayClass; } diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index 9f75a0d25..e2c0f746f 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -90,31 +90,13 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { }); } - @SuppressWarnings("unchecked") - private static Class getScreenClass(String type) throws ClassNotFoundException + private static Class getScreenClass(String type) throws ClassNotFoundException { - Class screenClass = NewtFactory.getCustomClass(type, "Screen"); + final Class screenClass = NewtFactory.getCustomClass(type, "ScreenDriver"); if(null==screenClass) { - if (NativeWindowFactory.TYPE_ANDROID == type) { - screenClass = Class.forName("jogamp.newt.driver.android.AndroidScreen"); - } else if (NativeWindowFactory.TYPE_EGL == type) { - screenClass = Class.forName("jogamp.newt.driver.kd.Screen"); - } else if (NativeWindowFactory.TYPE_WINDOWS == type) { - screenClass = Class.forName("jogamp.newt.driver.windows.WindowsScreen"); - } else if (NativeWindowFactory.TYPE_MACOSX == type) { - screenClass = Class.forName("jogamp.newt.driver.macosx.MacScreen"); - } else if (NativeWindowFactory.TYPE_X11 == type) { - screenClass = Class.forName("jogamp.newt.driver.x11.X11Screen"); - } else if (NativeWindowFactory.TYPE_AWT == type) { - screenClass = Class.forName("jogamp.newt.driver.awt.AWTScreen"); - } else { - throw new RuntimeException("Unknown window type \"" + type + "\""); - } - } - if(null==screenClass) { - throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".Screen>"); + throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".ScreenDriver>"); } - return (Class)screenClass; + return screenClass; } public static Screen create(Display display, int idx) { @@ -133,7 +115,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { } } synchronized(screenList) { - Class screenClass = getScreenClass(display.getType()); + Class screenClass = getScreenClass(display.getType()); ScreenImpl screen = (ScreenImpl) screenClass.newInstance(); screen.display = (DisplayImpl) display; idx = screen.validateScreenIndex(idx); diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 2971fa07e..ad7195944 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -152,26 +152,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private static Class getWindowClass(String type) throws ClassNotFoundException { - Class windowClass = NewtFactory.getCustomClass(type, "Window"); + final Class windowClass = NewtFactory.getCustomClass(type, "WindowDriver"); if(null==windowClass) { - if (NativeWindowFactory.TYPE_ANDROID == type) { - windowClass = Class.forName("jogamp.newt.driver.android.AndroidWindow"); - } else if (NativeWindowFactory.TYPE_EGL == type) { - windowClass = Class.forName("jogamp.newt.driver.kd.Window"); - } else if (NativeWindowFactory.TYPE_WINDOWS == type) { - windowClass = Class.forName("jogamp.newt.driver.windows.WindowsWindow"); - } else if (NativeWindowFactory.TYPE_MACOSX == type) { - windowClass = Class.forName("jogamp.newt.driver.macosx.MacWindow"); - } else if (NativeWindowFactory.TYPE_X11 == type) { - windowClass = Class.forName("jogamp.newt.driver.x11.X11Window"); - } else if (NativeWindowFactory.TYPE_AWT == type) { - windowClass = Class.forName("jogamp.newt.driver.awt.AWTWindow"); - } else { - throw new NativeWindowException("Unknown window type \"" + type + "\""); - } - } - if(null==windowClass) { - throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".Window>"); + throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".WindowDriver>"); } return windowClass; } diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java b/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java deleted file mode 100644 index 0a43c9b8f..000000000 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.android; - -import jogamp.newt.*; -import jogamp.opengl.egl.*; - -import javax.media.nativewindow.*; - -public class AndroidDisplay extends jogamp.newt.DisplayImpl { - static { - NEWTJNILibLoader.loadNEWT(); - - if (!AndroidWindow.initIDs0()) { - throw new NativeWindowException("Failed to initialize Android NEWT Windowing library"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public AndroidDisplay() { - } - - protected void createNativeImpl() { - // EGL Device - aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - } - - protected void closeNativeImpl() { - aDevice.close(); - } - - protected void dispatchMessagesNative() { - // n/a .. DispatchMessages(); - } -} - diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java b/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java deleted file mode 100644 index e108ed0bb..000000000 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.android; - -import javax.media.nativewindow.*; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.util.DisplayMetrics; -import android.view.Surface; -import android.view.WindowManager; - -public class AndroidScreen extends jogamp.newt.ScreenImpl { - - static { - AndroidDisplay.initSingleton(); - } - - public AndroidScreen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { } - - protected ScreenMode getCurrentScreenModeImpl() { - final Context ctx = jogamp.common.os.android.StaticContext.getContext(); - final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); - final DisplayMetrics outMetrics = new DisplayMetrics(); - final android.view.Display aDisplay = wmgr.getDefaultDisplay(); - aDisplay.getMetrics(outMetrics); - - final int arot = aDisplay.getRotation(); - final int nrot = androidRotation2NewtRotation(arot); - int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; - int offset = 1; // set later for verification of iterator - offset = getScreenSize(outMetrics, nrot, props, offset); - offset = getBpp(aDisplay, props, offset); - offset = getScreenSizeMM(outMetrics, props, offset); - props[offset++] = (int) aDisplay.getRefreshRate(); - props[offset++] = nrot; - props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count - return ScreenModeUtil.streamIn(props, 0); - } - - protected int validateScreenIndex(int idx) { - return 0; // FIXME: only one screen available ? - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - final ScreenMode sm = getCurrentScreenMode(); - virtualSize.setWidth(sm.getRotatedWidth()); - virtualSize.setHeight(sm.getRotatedHeight()); - } - - //---------------------------------------------------------------------- - // Internals only - // - static int androidRotation2NewtRotation(int arot) { - switch(arot) { - case Surface.ROTATION_270: return ScreenMode.ROTATE_270; - case Surface.ROTATION_180: return ScreenMode.ROTATE_180; - case Surface.ROTATION_90: return ScreenMode.ROTATE_90; - case Surface.ROTATION_0: - } - return ScreenMode.ROTATE_0; - } - static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) { - // swap width and height, since Android reflects rotated dimension, we don't - if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) { - props[offset++] = outMetrics.heightPixels; - props[offset++] = outMetrics.widthPixels; - } else { - props[offset++] = outMetrics.widthPixels; - props[offset++] = outMetrics.heightPixels; - } - return offset; - } - static int getBpp(android.view.Display aDisplay, int[] props, int offset) { - int bpp; - switch(aDisplay.getPixelFormat()) { - case PixelFormat.RGBA_8888: bpp=32; break; - case PixelFormat.RGBX_8888: bpp=32; break; - case PixelFormat.RGB_888: bpp=24; break; - case PixelFormat.RGB_565: bpp=16; break; - case PixelFormat.RGBA_5551: bpp=16; break; - case PixelFormat.RGBA_4444: bpp=16; break; - case PixelFormat.RGB_332: bpp= 8; break; - default: bpp=32; - } - props[offset++] = bpp; - return offset; - } - static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) { - final float iw = (float) outMetrics.widthPixels / outMetrics.xdpi; - final float ih = (float) outMetrics.heightPixels / outMetrics.xdpi; - final float mmpi = 25.4f; - props[offset++] = (int) ((iw * mmpi)+0.5); - props[offset++] = (int) ((ih * mmpi)+0.5); - return offset; - } -} - diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java deleted file mode 100644 index 73192a07f..000000000 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java +++ /dev/null @@ -1,458 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.android; - -import jogamp.common.os.android.StaticContext; -import jogamp.newt.driver.android.event.AndroidNewtEventFactory; - -import javax.media.nativewindow.Capabilities; -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.Point; -import javax.media.opengl.GLCapabilitiesChooser; -import javax.media.opengl.GLCapabilitiesImmutable; - -import com.jogamp.nativewindow.egl.EGLGraphicsDevice; - -import jogamp.opengl.egl.EGL; -import jogamp.opengl.egl.EGLGraphicsConfiguration; -import jogamp.opengl.egl.EGLGraphicsConfigurationFactory; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ResultReceiver; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceHolder.Callback2; -import android.view.inputmethod.InputMethodManager; -import android.view.SurfaceView; -import android.view.View; - -public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { - static { - AndroidDisplay.initSingleton(); - } - - public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) { - PixelFormat pf = new PixelFormat(); - PixelFormat.getPixelFormatInfo(format, pf); - final CapabilitiesImmutable res; - int r, g, b, a; - - switch(format) { - case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break; - case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break; - case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break; - case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break; - case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break; - case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break; - case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break; - default: throw new InternalError("Unhandled pixelformat: "+format); - } - final boolean change = matchFormatPrecise || - rCaps.getRedBits() > r && - rCaps.getGreenBits() > g && - rCaps.getBlueBits() > b && - rCaps.getAlphaBits() > a ; - - if(change) { - Capabilities nCaps = (Capabilities) rCaps.cloneMutable(); - nCaps.setRedBits(r); - nCaps.setGreenBits(g); - nCaps.setBlueBits(b); - nCaps.setAlphaBits(a); - res = nCaps; - } else { - res = rCaps; - } - Log.d(MD.TAG, "fixCaps: format: "+format); - Log.d(MD.TAG, "fixCaps: requested: "+rCaps); - Log.d(MD.TAG, "fixCaps: chosen: "+res); - - return res; - } - - public static int getFormat(CapabilitiesImmutable rCaps) { - int fmt = PixelFormat.UNKNOWN; - - if(!rCaps.isBackgroundOpaque()) { - fmt = PixelFormat.TRANSLUCENT; - } else if(rCaps.getRedBits()<=5 && - rCaps.getGreenBits()<=6 && - rCaps.getBlueBits()<=5 && - rCaps.getAlphaBits()==0) { - fmt = PixelFormat.RGB_565; - } - /* else if(rCaps.getRedBits()<=5 && - rCaps.getGreenBits()<=5 && - rCaps.getBlueBits()<=5 && - rCaps.getAlphaBits()==1) { - fmt = PixelFormat.RGBA_5551; // FIXME: Supported ? - } */ - else { - fmt = PixelFormat.RGBA_8888; - } - Log.d(MD.TAG, "getFormat: requested: "+rCaps); - Log.d(MD.TAG, "getFormat: returned: "+fmt); - - return fmt; - } - - public static boolean isAndroidFormatTransparent(int aFormat) { - switch (aFormat) { - case PixelFormat.TRANSLUCENT: - case PixelFormat.TRANSPARENT: - return true; - } - return false; - } - - class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener { - - @Override - public boolean onTouch(View v, android.view.MotionEvent event) { - final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, AndroidWindow.this); - if(null != newtEvents) { - focusChanged(false, true); - for(int i=0; i[] getCustomConstructorArgumentTypes() { - return new Class[] { Context.class } ; - } - - public AndroidWindow() { - reset(); - } - - private void reset() { - ownAndroidWindow = false; - androidView = null; - nativeFormat = VisualIDHolder.VID_UNDEFINED; - androidFormat = VisualIDHolder.VID_UNDEFINED; - capsByFormat = null; - surface = null; - surfaceHandle = 0; - eglSurface = 0; - definePosition(0, 0); // default to 0/0 - setBrokenFocusChange(true); - } - - @Override - protected void instantiationFinished() { - final Context ctx = StaticContext.getContext(); - if(null == ctx) { - throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first."); - } - androidView = new MSurfaceView(ctx); - - final AndroidEvents ae = new AndroidEvents(); - androidView.setOnTouchListener(ae); - androidView.setClickable(false); - androidView.setOnKeyListener(ae); - androidView.setOnFocusChangeListener(ae); - androidView.setFocusable(true); - androidView.setFocusableInTouchMode(true); - - final SurfaceHolder sh = androidView.getHolder(); - sh.addCallback(AndroidWindow.this); - sh.setFormat(getFormat(getRequestedCapabilities())); - - // default size -> TBD ! - defineSize(0, 0); - } - - public SurfaceView getAndroidView() { return androidView; } - - @Override - protected boolean canCreateNativeImpl() { - final boolean b = 0 != surfaceHandle; - Log.d(MD.TAG, "canCreateNativeImpl: "+b); - return b; - } - - @Override - protected void createNativeImpl() { - Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ - ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); - - if(0!=getParentWindowHandle()) { - throw new NativeWindowException("Window parenting not supported (yet)"); - } - if(0==surfaceHandle) { - throw new InternalError("XXX"); - } - - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); - final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(), - (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat, - isAndroidFormatTransparent(androidFormat)); - if (eglConfig == null) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE); - Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID)); - if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) { - setSurfaceVisualID0(surfaceHandle, nativeVisualID); - } - - eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null); - if (EGL.EGL_NO_SURFACE==eglSurface) { - throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError())); - } - - // propagate data .. - setGraphicsConfiguration(eglConfig); - setWindowHandle(surfaceHandle); - focusChanged(false, true); - Log.d(MD.TAG, "createNativeImpl X"); - } - - @Override - protected void closeNativeImpl() { - release0(surfaceHandle); - surface = null; - surfaceHandle = 0; - eglSurface = 0; - } - - @Override - public final long getSurfaceHandle() { - return eglSurface; - } - - protected void requestFocusImpl(boolean reparented) { - if(null != androidView) { - Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented); - androidView.post(new Runnable() { - public void run() { - androidView.requestFocus(); - androidView.bringToFront(); - } - }); - } - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a"); - return false; - } - if(width>0 || height>0) { - if(0!=getWindowHandle()) { - Log.d(MD.TAG, "reconfigureWindowImpl.setSize n/a"); - return false; - } - } - if(x>=0 || y>=0) { - Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a"); - return false; - } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return new Point(x,y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop .. - } - - //---------------------------------------------------------------------- - // Virtual On-Screen Keyboard / SoftInput - // - - private class KeyboardVisibleReceiver extends ResultReceiver { - public KeyboardVisibleReceiver() { - super(null); - } - - @Override - public void onReceiveResult(int r, Bundle data) { - boolean v = false; - - switch(r) { - case InputMethodManager.RESULT_UNCHANGED_SHOWN: - case InputMethodManager.RESULT_SHOWN: - v = true; - break; - case InputMethodManager.RESULT_HIDDEN: - case InputMethodManager.RESULT_UNCHANGED_HIDDEN: - v = false; - break; - } - Log.d(MD.TAG, "keyboardVisible: "+v); - keyboardVisibilityChanged(v); - } - } - private KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver(); - - protected final boolean setKeyboardVisibleImpl(boolean visible) { - if(null != androidView) { - final InputMethodManager imm = (InputMethodManager) getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - final IBinder winid = getAndroidView().getWindowToken(); - if(visible) { - // Show soft-keyboard: - imm.showSoftInput(androidView, 0, keyboardVisibleReceiver); - } else { - // hide keyboard : - imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver); - } - return visible; - } else { - return false; // nop - } - } - - //---------------------------------------------------------------------- - // Surface Callbacks - // - - public void surfaceCreated(SurfaceHolder holder) { - Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()); - } - - public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) { - Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)); - if(0!=surfaceHandle && androidFormat != aFormat ) { - // re-create - Log.d(MD.TAG, "surfaceChanged (destroy old)"); - if(!windowDestroyNotify(true)) { - destroy(); - } - surfaceHandle = 0; - surface=null; - } - if(getScreen().isNativeValid()) { - getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event - } - - if(0>getX() || 0>getY()) { - positionChanged(false, 0, 0); - } - - if(0 == surfaceHandle) { - androidFormat = aFormat; - surface = aHolder.getSurface(); - surfaceHandle = getSurfaceHandle0(surface); - acquire0(surfaceHandle); - nativeFormat = getSurfaceVisualID0(surfaceHandle); - final int nWidth = getWidth0(surfaceHandle); - final int nHeight = getHeight0(surfaceHandle); - capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities()); - sizeChanged(false, nWidth, nHeight, false); - - Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+ - ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ - ", format [a "+androidFormat+"/n "+nativeFormat+"], "+ - getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); - - if(isVisible()) { - setVisible(true); - } - } - sizeChanged(false, aWidth, aHeight, false); - windowRepaint(0, 0, aWidth, aHeight); - Log.d(MD.TAG, "surfaceChanged: X"); - } - - public void surfaceDestroyed(SurfaceHolder holder) { - Log.d(MD.TAG, "surfaceDestroyed"); - windowDestroyNotify(true); // actually too late .. however .. - } - - public void surfaceRedrawNeeded(SurfaceHolder holder) { - Log.d(MD.TAG, "surfaceRedrawNeeded"); - windowRepaint(0, 0, getWidth(), getHeight()); - } - - private boolean ownAndroidWindow; - private MSurfaceView androidView; - private int nativeFormat; // chosen current native PixelFormat (suitable for EGL) - private int androidFormat; // chosen current android PixelFormat (-1, -2 ..) - private GLCapabilitiesImmutable capsByFormat; // fixed requestedCaps by PixelFormat - private Surface surface; - private volatile long surfaceHandle; - private long eglSurface; - - class MSurfaceView extends SurfaceView { - public MSurfaceView (Context ctx) { - super(ctx); - setBackgroundDrawable(null); - // setBackgroundColor(Color.TRANSPARENT); - } - } - //---------------------------------------------------------------------- - // Internals only - // - protected static native boolean initIDs0(); - protected static native long getSurfaceHandle0(Surface surface); - protected static native int getSurfaceVisualID0(long surfaceHandle); - protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID); - protected static native int getWidth0(long surfaceHandle); - protected static native int getHeight0(long surfaceHandle); - protected static native void acquire0(long surfaceHandle); - protected static native void release0(long surfaceHandle); -} diff --git a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java new file mode 100644 index 000000000..a367462c4 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java @@ -0,0 +1,66 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.android; + +import jogamp.newt.*; +import jogamp.opengl.egl.*; + +import javax.media.nativewindow.*; + +public class DisplayDriver extends jogamp.newt.DisplayImpl { + static { + NEWTJNILibLoader.loadNEWT(); + + if (!WindowDriver.initIDs0()) { + throw new NativeWindowException("Failed to initialize Android NEWT Windowing library"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + protected void createNativeImpl() { + // EGL Device + aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + } + + protected void closeNativeImpl() { + aDevice.close(); + } + + protected void dispatchMessagesNative() { + // n/a .. DispatchMessages(); + } +} + diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java index 4537fa963..91c589beb 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java @@ -36,7 +36,7 @@ import javax.media.opengl.FPSCounter; import com.jogamp.newt.Window; import com.jogamp.opengl.util.Animator; -import jogamp.newt.driver.android.AndroidWindow; +import jogamp.newt.driver.android.WindowDriver; import android.app.Activity; import android.content.Context; @@ -83,10 +83,10 @@ public class NewtBaseActivity extends Activity { */ public void setContentView(android.view.Window androidWindow, Window newtWindow) { newtWindow = newtWindow.getDelegatedWindow(); - if(newtWindow instanceof AndroidWindow) { + if(newtWindow instanceof WindowDriver) { adaptTheme4Transparency(newtWindow.getRequestedCapabilities()); layoutForNEWTWindow(androidWindow, newtWindow); - AndroidWindow newtAWindow = (AndroidWindow)newtWindow; + WindowDriver newtAWindow = (WindowDriver)newtWindow; androidWindow.setContentView(newtAWindow.getAndroidView()); registerNEWTWindow(newtAWindow); } else { @@ -107,8 +107,8 @@ public class NewtBaseActivity extends Activity { */ public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) { newtWindow = newtWindow.getDelegatedWindow(); - if(newtWindow instanceof AndroidWindow) { - AndroidWindow newtAWindow = (AndroidWindow)newtWindow; + if(newtWindow instanceof WindowDriver) { + WindowDriver newtAWindow = (WindowDriver)newtWindow; androidWindow.addContentView(newtAWindow.getAndroidView(), params); registerNEWTWindow(newtAWindow); } else { diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java index 36b83337a..a49f1648c 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java @@ -69,7 +69,7 @@ public class NewtVersionActivity extends NewtBaseActivity { glWindow.setUndecorated(true); glWindow.setSize(32, 32); glWindow.setPosition(0, 0); - final android.view.View androidGLView = ((AndroidWindow)glWindow.getDelegatedWindow()).getAndroidView(); + final android.view.View androidGLView = ((WindowDriver)glWindow.getDelegatedWindow()).getAndroidView(); viewGroup.addView(androidGLView, new android.widget.FrameLayout.LayoutParams(glWindow.getWidth(), glWindow.getHeight(), Gravity.BOTTOM|Gravity.RIGHT)); registerNEWTWindow(glWindow); diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java new file mode 100644 index 000000000..795aac5fb --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java @@ -0,0 +1,138 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.android; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.util.DisplayMetrics; +import android.view.Surface; +import android.view.WindowManager; + +public class ScreenDriver extends jogamp.newt.ScreenImpl { + + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { } + + protected ScreenMode getCurrentScreenModeImpl() { + final Context ctx = jogamp.common.os.android.StaticContext.getContext(); + final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); + final DisplayMetrics outMetrics = new DisplayMetrics(); + final android.view.Display aDisplay = wmgr.getDefaultDisplay(); + aDisplay.getMetrics(outMetrics); + + final int arot = aDisplay.getRotation(); + final int nrot = androidRotation2NewtRotation(arot); + int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; + int offset = 1; // set later for verification of iterator + offset = getScreenSize(outMetrics, nrot, props, offset); + offset = getBpp(aDisplay, props, offset); + offset = getScreenSizeMM(outMetrics, props, offset); + props[offset++] = (int) aDisplay.getRefreshRate(); + props[offset++] = nrot; + props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count + return ScreenModeUtil.streamIn(props, 0); + } + + protected int validateScreenIndex(int idx) { + return 0; // FIXME: only one screen available ? + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + final ScreenMode sm = getCurrentScreenMode(); + virtualSize.setWidth(sm.getRotatedWidth()); + virtualSize.setHeight(sm.getRotatedHeight()); + } + + //---------------------------------------------------------------------- + // Internals only + // + static int androidRotation2NewtRotation(int arot) { + switch(arot) { + case Surface.ROTATION_270: return ScreenMode.ROTATE_270; + case Surface.ROTATION_180: return ScreenMode.ROTATE_180; + case Surface.ROTATION_90: return ScreenMode.ROTATE_90; + case Surface.ROTATION_0: + } + return ScreenMode.ROTATE_0; + } + static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) { + // swap width and height, since Android reflects rotated dimension, we don't + if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) { + props[offset++] = outMetrics.heightPixels; + props[offset++] = outMetrics.widthPixels; + } else { + props[offset++] = outMetrics.widthPixels; + props[offset++] = outMetrics.heightPixels; + } + return offset; + } + static int getBpp(android.view.Display aDisplay, int[] props, int offset) { + int bpp; + switch(aDisplay.getPixelFormat()) { + case PixelFormat.RGBA_8888: bpp=32; break; + case PixelFormat.RGBX_8888: bpp=32; break; + case PixelFormat.RGB_888: bpp=24; break; + case PixelFormat.RGB_565: bpp=16; break; + case PixelFormat.RGBA_5551: bpp=16; break; + case PixelFormat.RGBA_4444: bpp=16; break; + case PixelFormat.RGB_332: bpp= 8; break; + default: bpp=32; + } + props[offset++] = bpp; + return offset; + } + static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) { + final float iw = (float) outMetrics.widthPixels / outMetrics.xdpi; + final float ih = (float) outMetrics.heightPixels / outMetrics.xdpi; + final float mmpi = 25.4f; + props[offset++] = (int) ((iw * mmpi)+0.5); + props[offset++] = (int) ((ih * mmpi)+0.5); + return offset; + } +} + diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java new file mode 100644 index 000000000..8ad11b35f --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -0,0 +1,458 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.android; + +import jogamp.common.os.android.StaticContext; +import jogamp.newt.driver.android.event.AndroidNewtEventFactory; + +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; + +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +import jogamp.opengl.egl.EGL; +import jogamp.opengl.egl.EGLGraphicsConfiguration; +import jogamp.opengl.egl.EGLGraphicsConfigurationFactory; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ResultReceiver; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceHolder.Callback2; +import android.view.inputmethod.InputMethodManager; +import android.view.SurfaceView; +import android.view.View; + +public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { + static { + DisplayDriver.initSingleton(); + } + + public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) { + PixelFormat pf = new PixelFormat(); + PixelFormat.getPixelFormatInfo(format, pf); + final CapabilitiesImmutable res; + int r, g, b, a; + + switch(format) { + case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break; + case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break; + case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break; + case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break; + case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break; + case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break; + case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break; + default: throw new InternalError("Unhandled pixelformat: "+format); + } + final boolean change = matchFormatPrecise || + rCaps.getRedBits() > r && + rCaps.getGreenBits() > g && + rCaps.getBlueBits() > b && + rCaps.getAlphaBits() > a ; + + if(change) { + Capabilities nCaps = (Capabilities) rCaps.cloneMutable(); + nCaps.setRedBits(r); + nCaps.setGreenBits(g); + nCaps.setBlueBits(b); + nCaps.setAlphaBits(a); + res = nCaps; + } else { + res = rCaps; + } + Log.d(MD.TAG, "fixCaps: format: "+format); + Log.d(MD.TAG, "fixCaps: requested: "+rCaps); + Log.d(MD.TAG, "fixCaps: chosen: "+res); + + return res; + } + + public static int getFormat(CapabilitiesImmutable rCaps) { + int fmt = PixelFormat.UNKNOWN; + + if(!rCaps.isBackgroundOpaque()) { + fmt = PixelFormat.TRANSLUCENT; + } else if(rCaps.getRedBits()<=5 && + rCaps.getGreenBits()<=6 && + rCaps.getBlueBits()<=5 && + rCaps.getAlphaBits()==0) { + fmt = PixelFormat.RGB_565; + } + /* else if(rCaps.getRedBits()<=5 && + rCaps.getGreenBits()<=5 && + rCaps.getBlueBits()<=5 && + rCaps.getAlphaBits()==1) { + fmt = PixelFormat.RGBA_5551; // FIXME: Supported ? + } */ + else { + fmt = PixelFormat.RGBA_8888; + } + Log.d(MD.TAG, "getFormat: requested: "+rCaps); + Log.d(MD.TAG, "getFormat: returned: "+fmt); + + return fmt; + } + + public static boolean isAndroidFormatTransparent(int aFormat) { + switch (aFormat) { + case PixelFormat.TRANSLUCENT: + case PixelFormat.TRANSPARENT: + return true; + } + return false; + } + + class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener { + + @Override + public boolean onTouch(View v, android.view.MotionEvent event) { + final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, WindowDriver.this); + if(null != newtEvents) { + focusChanged(false, true); + for(int i=0; i[] getCustomConstructorArgumentTypes() { + return new Class[] { Context.class } ; + } + + public WindowDriver() { + reset(); + } + + private void reset() { + ownAndroidWindow = false; + androidView = null; + nativeFormat = VisualIDHolder.VID_UNDEFINED; + androidFormat = VisualIDHolder.VID_UNDEFINED; + capsByFormat = null; + surface = null; + surfaceHandle = 0; + eglSurface = 0; + definePosition(0, 0); // default to 0/0 + setBrokenFocusChange(true); + } + + @Override + protected void instantiationFinished() { + final Context ctx = StaticContext.getContext(); + if(null == ctx) { + throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first."); + } + androidView = new MSurfaceView(ctx); + + final AndroidEvents ae = new AndroidEvents(); + androidView.setOnTouchListener(ae); + androidView.setClickable(false); + androidView.setOnKeyListener(ae); + androidView.setOnFocusChangeListener(ae); + androidView.setFocusable(true); + androidView.setFocusableInTouchMode(true); + + final SurfaceHolder sh = androidView.getHolder(); + sh.addCallback(WindowDriver.this); + sh.setFormat(getFormat(getRequestedCapabilities())); + + // default size -> TBD ! + defineSize(0, 0); + } + + public SurfaceView getAndroidView() { return androidView; } + + @Override + protected boolean canCreateNativeImpl() { + final boolean b = 0 != surfaceHandle; + Log.d(MD.TAG, "canCreateNativeImpl: "+b); + return b; + } + + @Override + protected void createNativeImpl() { + Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ + ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); + + if(0!=getParentWindowHandle()) { + throw new NativeWindowException("Window parenting not supported (yet)"); + } + if(0==surfaceHandle) { + throw new InternalError("XXX"); + } + + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); + final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(), + (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat, + isAndroidFormatTransparent(androidFormat)); + if (eglConfig == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE); + Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID)); + if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) { + setSurfaceVisualID0(surfaceHandle, nativeVisualID); + } + + eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null); + if (EGL.EGL_NO_SURFACE==eglSurface) { + throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError())); + } + + // propagate data .. + setGraphicsConfiguration(eglConfig); + setWindowHandle(surfaceHandle); + focusChanged(false, true); + Log.d(MD.TAG, "createNativeImpl X"); + } + + @Override + protected void closeNativeImpl() { + release0(surfaceHandle); + surface = null; + surfaceHandle = 0; + eglSurface = 0; + } + + @Override + public final long getSurfaceHandle() { + return eglSurface; + } + + protected void requestFocusImpl(boolean reparented) { + if(null != androidView) { + Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented); + androidView.post(new Runnable() { + public void run() { + androidView.requestFocus(); + androidView.bringToFront(); + } + }); + } + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { + Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a"); + return false; + } + if(width>0 || height>0) { + if(0!=getWindowHandle()) { + Log.d(MD.TAG, "reconfigureWindowImpl.setSize n/a"); + return false; + } + } + if(x>=0 || y>=0) { + Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a"); + return false; + } + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop .. + } + + //---------------------------------------------------------------------- + // Virtual On-Screen Keyboard / SoftInput + // + + private class KeyboardVisibleReceiver extends ResultReceiver { + public KeyboardVisibleReceiver() { + super(null); + } + + @Override + public void onReceiveResult(int r, Bundle data) { + boolean v = false; + + switch(r) { + case InputMethodManager.RESULT_UNCHANGED_SHOWN: + case InputMethodManager.RESULT_SHOWN: + v = true; + break; + case InputMethodManager.RESULT_HIDDEN: + case InputMethodManager.RESULT_UNCHANGED_HIDDEN: + v = false; + break; + } + Log.d(MD.TAG, "keyboardVisible: "+v); + keyboardVisibilityChanged(v); + } + } + private KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver(); + + protected final boolean setKeyboardVisibleImpl(boolean visible) { + if(null != androidView) { + final InputMethodManager imm = (InputMethodManager) getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + final IBinder winid = getAndroidView().getWindowToken(); + if(visible) { + // Show soft-keyboard: + imm.showSoftInput(androidView, 0, keyboardVisibleReceiver); + } else { + // hide keyboard : + imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver); + } + return visible; + } else { + return false; // nop + } + } + + //---------------------------------------------------------------------- + // Surface Callbacks + // + + public void surfaceCreated(SurfaceHolder holder) { + Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()); + } + + public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) { + Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)); + if(0!=surfaceHandle && androidFormat != aFormat ) { + // re-create + Log.d(MD.TAG, "surfaceChanged (destroy old)"); + if(!windowDestroyNotify(true)) { + destroy(); + } + surfaceHandle = 0; + surface=null; + } + if(getScreen().isNativeValid()) { + getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event + } + + if(0>getX() || 0>getY()) { + positionChanged(false, 0, 0); + } + + if(0 == surfaceHandle) { + androidFormat = aFormat; + surface = aHolder.getSurface(); + surfaceHandle = getSurfaceHandle0(surface); + acquire0(surfaceHandle); + nativeFormat = getSurfaceVisualID0(surfaceHandle); + final int nWidth = getWidth0(surfaceHandle); + final int nHeight = getHeight0(surfaceHandle); + capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities()); + sizeChanged(false, nWidth, nHeight, false); + + Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+ + ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ + ", format [a "+androidFormat+"/n "+nativeFormat+"], "+ + getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); + + if(isVisible()) { + setVisible(true); + } + } + sizeChanged(false, aWidth, aHeight, false); + windowRepaint(0, 0, aWidth, aHeight); + Log.d(MD.TAG, "surfaceChanged: X"); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + Log.d(MD.TAG, "surfaceDestroyed"); + windowDestroyNotify(true); // actually too late .. however .. + } + + public void surfaceRedrawNeeded(SurfaceHolder holder) { + Log.d(MD.TAG, "surfaceRedrawNeeded"); + windowRepaint(0, 0, getWidth(), getHeight()); + } + + private boolean ownAndroidWindow; + private MSurfaceView androidView; + private int nativeFormat; // chosen current native PixelFormat (suitable for EGL) + private int androidFormat; // chosen current android PixelFormat (-1, -2 ..) + private GLCapabilitiesImmutable capsByFormat; // fixed requestedCaps by PixelFormat + private Surface surface; + private volatile long surfaceHandle; + private long eglSurface; + + class MSurfaceView extends SurfaceView { + public MSurfaceView (Context ctx) { + super(ctx); + setBackgroundDrawable(null); + // setBackgroundColor(Color.TRANSPARENT); + } + } + //---------------------------------------------------------------------- + // Internals only + // + protected static native boolean initIDs0(); + protected static native long getSurfaceHandle0(Surface surface); + protected static native int getSurfaceVisualID0(long surfaceHandle); + protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID); + protected static native int getWidth0(long surfaceHandle); + protected static native int getHeight0(long surfaceHandle); + protected static native void acquire0(long surfaceHandle); + protected static native void release0(long surfaceHandle); +} diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index a7950048a..b3fdcad41 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java deleted file mode 100644 index 65f8b4715..000000000 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.awt; - -import com.jogamp.nativewindow.awt.AWTGraphicsDevice; -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.util.EDTUtil; - -import jogamp.newt.DisplayImpl; - -public class AWTDisplay extends DisplayImpl { - public AWTDisplay() { - } - - protected void createNativeImpl() { - aDevice = AWTGraphicsDevice.createDefault(); - } - - protected void setAWTGraphicsDevice(AWTGraphicsDevice d) { - aDevice = d; - } - - protected void closeNativeImpl() { } - - @Override - protected EDTUtil createEDTUtil() { - final EDTUtil def; - if(NewtFactory.useEDT()) { - def = AWTEDTUtil.getSingleton(); - if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); - } - } else { - def = null; - } - return def; - } - - protected void dispatchMessagesNative() { /* nop */ } -} - diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java b/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java deleted file mode 100644 index a3c0281b1..000000000 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.awt; - -import java.awt.DisplayMode; - -import jogamp.newt.ScreenImpl; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import com.jogamp.nativewindow.awt.AWTGraphicsDevice; -import com.jogamp.nativewindow.awt.AWTGraphicsScreen; - -public class AWTScreen extends ScreenImpl { - public AWTScreen() { - } - - protected void createNativeImpl() { - aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); - } - - protected void setAWTGraphicsScreen(AWTGraphicsScreen s) { - aScreen = s; - } - - /** - * Used by AWTWindow .. - */ - @Override - protected void updateVirtualScreenOriginAndSize() { - super.updateVirtualScreenOriginAndSize(); - } - - protected void closeNativeImpl() { } - - protected int validateScreenIndex(int idx) { - return idx; // pass through ... - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); - if(null != mode) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(mode.getWidth()); - virtualSize.setHeight(mode.getHeight()); - } - } - -} diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java deleted file mode 100644 index 2b2fed545..000000000 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.awt; - -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Frame; -import java.awt.Insets; - -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.WindowImpl; - -import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; -import com.jogamp.nativewindow.awt.AWTGraphicsDevice; -import com.jogamp.nativewindow.awt.AWTGraphicsScreen; -import com.jogamp.newt.event.awt.AWTKeyAdapter; -import com.jogamp.newt.event.awt.AWTMouseAdapter; -import com.jogamp.newt.event.awt.AWTWindowAdapter; - -/** An implementation of the Newt Window class built using the - AWT. This is provided for convenience of porting to platforms - supporting Java SE. */ - -public class AWTWindow extends WindowImpl { - - public AWTWindow() { - this(null); - } - - public static Class[] getCustomConstructorArgumentTypes() { - return new Class[] { Container.class } ; - } - - public AWTWindow(Container container) { - super(); - this.container = container; - if(container instanceof Frame) { - frame = (Frame) container; - } - } - - private boolean owningFrame; - private Container container = null; - private Frame frame = null; // same instance as container, just for impl. convenience - private AWTCanvas canvas; - - protected void requestFocusImpl(boolean reparented) { - container.requestFocus(); - } - - @Override - protected void setTitleImpl(final String title) { - if (frame != null) { - frame.setTitle(title); - } - } - - protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead"); - } - - if(null==container) { - frame = new Frame(); - container = frame; - owningFrame=true; - } else { - owningFrame=false; - defineSize(container.getWidth(), container.getHeight()); - definePosition(container.getX(), container.getY()); - } - if(null!=frame) { - frame.setTitle(getTitle()); - } - container.setLayout(new BorderLayout()); - canvas = new AWTCanvas(capsRequested, AWTWindow.this.capabilitiesChooser); - - addWindowListener(new LocalWindowListener()); - - new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here - new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here - - // canvas.addComponentListener(listener); - container.add(canvas, BorderLayout.CENTER); - container.setSize(getWidth(), getHeight()); - container.setLocation(getX(), getY()); - new AWTWindowAdapter(this).addTo(container); // fwd all AWT Window events to here - - reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true)); - // throws exception if failed .. - - setWindowHandle(1); // just a marker .. - } - - protected void closeNativeImpl() { - setWindowHandle(0); // just a marker .. - if(null!=container) { - container.setVisible(false); - container.remove(canvas); - container.setEnabled(false); - canvas.setEnabled(false); - } - if(owningFrame && null!=frame) { - frame.dispose(); - owningFrame=false; - frame = null; - } - } - - @Override - public boolean hasDeviceChanged() { - boolean res = canvas.hasDeviceChanged(); - if(res) { - final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); - if (null == cfg) { - throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this); - } - setGraphicsConfiguration(cfg); - - // propagate new info .. - ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen()); - ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice()); - - ((AWTScreen)getScreen()).updateVirtualScreenOriginAndSize(); - } - return res; - } - - protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) { - Insets contInsets = container.getInsets(); - insets.setLeftWidth(contInsets.left); - insets.setRightWidth(contInsets.right); - insets.setTopHeight(contInsets.top); - insets.setBottomHeight(contInsets.bottom); - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=frame) { - if(!container.isDisplayable()) { - frame.setUndecorated(isUndecorated()); - } else { - if(DEBUG_IMPLEMENTATION) { - System.err.println("AWTWindow can't undecorate already created frame"); - } - } - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - container.setVisible(0 != ( FLAG_IS_VISIBLE & flags)); - } - - container.setLocation(x, y); - Insets insets = container.getInsets(); - container.setSize(width + insets.left + insets.right, - height + insets.top + insets.bottom); - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - if( 0 != ( FLAG_IS_VISIBLE & flags ) ) { - if( !hasDeviceChanged() ) { - // oops ?? - final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); - if(null == cfg) { - throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this); - } - setGraphicsConfiguration(cfg); - } - } - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - java.awt.Point ap = canvas.getLocationOnScreen(); - ap.translate(x, y); - return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5)); - } - - @Override - public Object getWrappedWindow() { - return canvas; - } - - class LocalWindowListener extends com.jogamp.newt.event.WindowAdapter { - @Override - public void windowMoved(com.jogamp.newt.event.WindowEvent e) { - if(null!=container) { - definePosition(container.getX(), container.getY()); - } - } - @Override - public void windowResized(com.jogamp.newt.event.WindowEvent e) { - if(null!=canvas) { - defineSize(canvas.getWidth(), canvas.getHeight()); - } - } - } -} diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java new file mode 100644 index 000000000..39d96585b --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.awt; + +import com.jogamp.nativewindow.awt.AWTGraphicsDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; + +import jogamp.newt.DisplayImpl; + +public class DisplayDriver extends DisplayImpl { + public DisplayDriver() { + } + + protected void createNativeImpl() { + aDevice = AWTGraphicsDevice.createDefault(); + } + + protected void setAWTGraphicsDevice(AWTGraphicsDevice d) { + aDevice = d; + } + + protected void closeNativeImpl() { } + + @Override + protected EDTUtil createEDTUtil() { + final EDTUtil def; + if(NewtFactory.useEDT()) { + def = AWTEDTUtil.getSingleton(); + if(DEBUG) { + System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); + } + } else { + def = null; + } + return def; + } + + protected void dispatchMessagesNative() { /* nop */ } +} + diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java new file mode 100644 index 000000000..6b1283a00 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.awt; + +import java.awt.DisplayMode; + +import jogamp.newt.ScreenImpl; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import com.jogamp.nativewindow.awt.AWTGraphicsDevice; +import com.jogamp.nativewindow.awt.AWTGraphicsScreen; + +public class ScreenDriver extends ScreenImpl { + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); + } + + protected void setAWTGraphicsScreen(AWTGraphicsScreen s) { + aScreen = s; + } + + /** + * Used by AWTWindow .. + */ + @Override + protected void updateVirtualScreenOriginAndSize() { + super.updateVirtualScreenOriginAndSize(); + } + + protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return idx; // pass through ... + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); + if(null != mode) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(mode.getWidth()); + virtualSize.setHeight(mode.getHeight()); + } + } + +} diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java new file mode 100644 index 000000000..1723ffee5 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.awt; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Insets; + +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.WindowImpl; + +import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; +import com.jogamp.nativewindow.awt.AWTGraphicsDevice; +import com.jogamp.nativewindow.awt.AWTGraphicsScreen; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTMouseAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; + +/** An implementation of the Newt Window class built using the + AWT. This is provided for convenience of porting to platforms + supporting Java SE. */ + +public class WindowDriver extends WindowImpl { + + public WindowDriver() { + this(null); + } + + public static Class[] getCustomConstructorArgumentTypes() { + return new Class[] { Container.class } ; + } + + public WindowDriver(Container container) { + super(); + this.container = container; + if(container instanceof Frame) { + frame = (Frame) container; + } + } + + private boolean owningFrame; + private Container container = null; + private Frame frame = null; // same instance as container, just for impl. convenience + private AWTCanvas canvas; + + protected void requestFocusImpl(boolean reparented) { + container.requestFocus(); + } + + @Override + protected void setTitleImpl(final String title) { + if (frame != null) { + frame.setTitle(title); + } + } + + protected void createNativeImpl() { + if(0!=getParentWindowHandle()) { + throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead"); + } + + if(null==container) { + frame = new Frame(); + container = frame; + owningFrame=true; + } else { + owningFrame=false; + defineSize(container.getWidth(), container.getHeight()); + definePosition(container.getX(), container.getY()); + } + if(null!=frame) { + frame.setTitle(getTitle()); + } + container.setLayout(new BorderLayout()); + canvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser); + + addWindowListener(new LocalWindowListener()); + + new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here + new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here + + // canvas.addComponentListener(listener); + container.add(canvas, BorderLayout.CENTER); + container.setSize(getWidth(), getHeight()); + container.setLocation(getX(), getY()); + new AWTWindowAdapter(this).addTo(container); // fwd all AWT Window events to here + + reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true)); + // throws exception if failed .. + + setWindowHandle(1); // just a marker .. + } + + protected void closeNativeImpl() { + setWindowHandle(0); // just a marker .. + if(null!=container) { + container.setVisible(false); + container.remove(canvas); + container.setEnabled(false); + canvas.setEnabled(false); + } + if(owningFrame && null!=frame) { + frame.dispose(); + owningFrame=false; + frame = null; + } + } + + @Override + public boolean hasDeviceChanged() { + boolean res = canvas.hasDeviceChanged(); + if(res) { + final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); + if (null == cfg) { + throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this); + } + setGraphicsConfiguration(cfg); + + // propagate new info .. + ((ScreenDriver)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen()); + ((DisplayDriver)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice()); + + ((ScreenDriver)getScreen()).updateVirtualScreenOriginAndSize(); + } + return res; + } + + protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) { + Insets contInsets = container.getInsets(); + insets.setLeftWidth(contInsets.left); + insets.setRightWidth(contInsets.right); + insets.setTopHeight(contInsets.top); + insets.setBottomHeight(contInsets.bottom); + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=frame) { + if(!container.isDisplayable()) { + frame.setUndecorated(isUndecorated()); + } else { + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWTWindow can't undecorate already created frame"); + } + } + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + container.setVisible(0 != ( FLAG_IS_VISIBLE & flags)); + } + + container.setLocation(x, y); + Insets insets = container.getInsets(); + container.setSize(width + insets.left + insets.right, + height + insets.top + insets.bottom); + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + if( 0 != ( FLAG_IS_VISIBLE & flags ) ) { + if( !hasDeviceChanged() ) { + // oops ?? + final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); + if(null == cfg) { + throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this); + } + setGraphicsConfiguration(cfg); + } + } + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + java.awt.Point ap = canvas.getLocationOnScreen(); + ap.translate(x, y); + return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5)); + } + + @Override + public Object getWrappedWindow() { + return canvas; + } + + class LocalWindowListener extends com.jogamp.newt.event.WindowAdapter { + @Override + public void windowMoved(com.jogamp.newt.event.WindowEvent e) { + if(null!=container) { + definePosition(container.getX(), container.getY()); + } + } + @Override + public void windowResized(com.jogamp.newt.event.WindowEvent e) { + if(null!=canvas) { + defineSize(canvas.getWidth(), canvas.getHeight()); + } + } + } +} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/Display.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/Display.java deleted file mode 100644 index f08890da6..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/Display.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.bcm.egl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; - -import jogamp.newt.NEWTJNILibLoader; -import jogamp.opengl.egl.EGL; - -import com.jogamp.nativewindow.egl.EGLGraphicsDevice; - -public class Display extends jogamp.newt.DisplayImpl { - - static { - NEWTJNILibLoader.loadNEWT(); - - if (!Window.initIDs()) { - throw new NativeWindowException("Failed to initialize BCEGL Window jmethodIDs"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public Display() { - } - - protected void createNativeImpl() { - final long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); - if (handle == EGL.EGL_NO_DISPLAY) { - throw new NativeWindowException("BC EGL CreateDisplay failed"); - } - aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null); - } - - protected void closeNativeImpl() { - if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { - DestroyDisplay(aDevice.getHandle()); - } - } - - protected void dispatchMessagesNative() { - // n/a .. DispatchMessages(); - } - - private native long CreateDisplay(int width, int height); - private native void DestroyDisplay(long dpy); - private native void DispatchMessages(); -} - diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java new file mode 100644 index 000000000..65ca63eec --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.bcm.egl; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; + +import jogamp.newt.NEWTJNILibLoader; +import jogamp.opengl.egl.EGL; + +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +public class DisplayDriver extends jogamp.newt.DisplayImpl { + + static { + NEWTJNILibLoader.loadNEWT(); + + if (!WindowDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize BCEGL Window jmethodIDs"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + protected void createNativeImpl() { + final long handle = CreateDisplay(ScreenDriver.fixedWidth, ScreenDriver.fixedHeight); + if (handle == EGL.EGL_NO_DISPLAY) { + throw new NativeWindowException("BC EGL CreateDisplay failed"); + } + aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null); + } + + protected void closeNativeImpl() { + if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { + DestroyDisplay(aDevice.getHandle()); + } + } + + protected void dispatchMessagesNative() { + // n/a .. DispatchMessages(); + } + + private native long CreateDisplay(int width, int height); + private native void DestroyDisplay(long dpy); + private native void DispatchMessages(); +} + diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/Screen.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/Screen.java deleted file mode 100644 index 909444d24..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/Screen.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.bcm.egl; - -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -public class Screen extends jogamp.newt.ScreenImpl { - - static { - Display.initSingleton(); - } - - - public Screen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { } - - protected int validateScreenIndex(int idx) { - return 0; // only one screen available - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(fixedWidth); // FIXME - virtualSize.setHeight(fixedHeight); // FIXME - } - - //---------------------------------------------------------------------- - // Internals only - // - - static final int fixedWidth = 1920; // FIXME - static final int fixedHeight = 1080; // FIXME -} - diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java new file mode 100644 index 000000000..deb2a534b --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.bcm.egl; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +public class ScreenDriver extends jogamp.newt.ScreenImpl { + + static { + DisplayDriver.initSingleton(); + } + + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(fixedWidth); // FIXME + virtualSize.setHeight(fixedHeight); // FIXME + } + + //---------------------------------------------------------------------- + // Internals only + // + + static final int fixedWidth = 1920; // FIXME + static final int fixedHeight = 1080; // FIXME +} + diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/Window.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/Window.java deleted file mode 100644 index 87170e4ab..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/Window.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.bcm.egl; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.Point; -import javax.media.opengl.GLCapabilitiesImmutable; - -import jogamp.opengl.egl.EGLGraphicsConfiguration; - -public class Window extends jogamp.newt.WindowImpl { - static { - Display.initSingleton(); - } - - public Window() { - } - - protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new RuntimeException("Window parenting not supported (yet)"); - } - // query a good configuration, however chose the final one by the native queried egl-cfg-id - // after creation at {@link #windowCreated(int, int, int)}. - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - setSizeImpl(getScreen().getWidth(), getScreen().getHeight()); - - setWindowHandle(realizeWindow(true, getWidth(), getHeight())); - if (0 == getWindowHandle()) { - throw new NativeWindowException("Error native Window Handle is null"); - } - } - - protected void closeNativeImpl() { - if(0!=windowHandleClose) { - CloseWindow(getDisplayHandle(), windowHandleClose); - } - } - - protected void requestFocusImpl(boolean reparented) { } - - protected void setSizeImpl(int width, int height) { - if(0!=getWindowHandle()) { - // n/a in BroadcomEGL - System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); - } else { - defineSize(width, height); - } - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if(0!=getWindowHandle()) { - if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { - if( 0 != ( FLAG_IS_FULLSCREEN & flags) ) { - // n/a in BroadcomEGL - System.err.println("setFullscreen n/a in BroadcomEGL"); - return false; - } - } - } - if(width>0 || height>0) { - if(0!=getWindowHandle()) { - // n/a in BroadcomEGL - System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); - } else { - defineSize((width>0)?width:getWidth(), (height>0)?height:getHeight()); - } - } - if(x>=0 || y>=0) { - System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return new Point(x,y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop .. - } - - @Override - public boolean surfaceSwap() { - SwapWindow(getDisplayHandle(), getWindowHandle()); - return true; - } - - //---------------------------------------------------------------------- - // Internals only - // - - protected static native boolean initIDs(); - private native long CreateWindow(long eglDisplayHandle, boolean chromaKey, int width, int height); - private native void CloseWindow(long eglDisplayHandle, long eglWindowHandle); - private native void SwapWindow(long eglDisplayHandle, long eglWindowHandle); - - - private long realizeWindow(boolean chromaKey, int width, int height) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("BCEGL Window.realizeWindow() with: chroma "+chromaKey+", "+width+"x"+height+", "+getGraphicsConfiguration()); - } - long handle = CreateWindow(getDisplayHandle(), chromaKey, width, height); - if (0 == handle) { - throw new NativeWindowException("Error native Window Handle is null"); - } - windowHandleClose = handle; - return handle; - } - - private void windowCreated(int cfgID, int width, int height) { - defineSize(width, height); - GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities(); - final AbstractGraphicsConfiguration cfg = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID); - if (null == cfg) { - throw new NativeWindowException("Error creating EGLGraphicsConfiguration from id: "+cfgID+", "+this); - } - setGraphicsConfiguration(cfg); - if(DEBUG_IMPLEMENTATION) { - System.err.println("BCEGL Window.windowCreated(): "+toHexString(cfgID)+", "+width+"x"+height+", "+cfg); - } - } - - private long windowHandleClose; -} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java new file mode 100644 index 000000000..49d3d98ba --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.bcm.egl; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; +import javax.media.opengl.GLCapabilitiesImmutable; + +import jogamp.opengl.egl.EGLGraphicsConfiguration; + +public class WindowDriver extends jogamp.newt.WindowImpl { + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + protected void createNativeImpl() { + if(0!=getParentWindowHandle()) { + throw new RuntimeException("Window parenting not supported (yet)"); + } + // query a good configuration, however chose the final one by the native queried egl-cfg-id + // after creation at {@link #windowCreated(int, int, int)}. + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + setSizeImpl(getScreen().getWidth(), getScreen().getHeight()); + + setWindowHandle(realizeWindow(true, getWidth(), getHeight())); + if (0 == getWindowHandle()) { + throw new NativeWindowException("Error native Window Handle is null"); + } + } + + protected void closeNativeImpl() { + if(0!=windowHandleClose) { + CloseWindow(getDisplayHandle(), windowHandleClose); + } + } + + protected void requestFocusImpl(boolean reparented) { } + + protected void setSizeImpl(int width, int height) { + if(0!=getWindowHandle()) { + // n/a in BroadcomEGL + System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); + } else { + defineSize(width, height); + } + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if(0!=getWindowHandle()) { + if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { + if( 0 != ( FLAG_IS_FULLSCREEN & flags) ) { + // n/a in BroadcomEGL + System.err.println("setFullscreen n/a in BroadcomEGL"); + return false; + } + } + } + if(width>0 || height>0) { + if(0!=getWindowHandle()) { + // n/a in BroadcomEGL + System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); + } else { + defineSize((width>0)?width:getWidth(), (height>0)?height:getHeight()); + } + } + if(x>=0 || y>=0) { + System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop .. + } + + @Override + public boolean surfaceSwap() { + SwapWindow(getDisplayHandle(), getWindowHandle()); + return true; + } + + //---------------------------------------------------------------------- + // Internals only + // + + protected static native boolean initIDs(); + private native long CreateWindow(long eglDisplayHandle, boolean chromaKey, int width, int height); + private native void CloseWindow(long eglDisplayHandle, long eglWindowHandle); + private native void SwapWindow(long eglDisplayHandle, long eglWindowHandle); + + + private long realizeWindow(boolean chromaKey, int width, int height) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("BCEGL Window.realizeWindow() with: chroma "+chromaKey+", "+width+"x"+height+", "+getGraphicsConfiguration()); + } + long handle = CreateWindow(getDisplayHandle(), chromaKey, width, height); + if (0 == handle) { + throw new NativeWindowException("Error native Window Handle is null"); + } + windowHandleClose = handle; + return handle; + } + + private void windowCreated(int cfgID, int width, int height) { + defineSize(width, height); + GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities(); + final AbstractGraphicsConfiguration cfg = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID); + if (null == cfg) { + throw new NativeWindowException("Error creating EGLGraphicsConfiguration from id: "+cfgID+", "+this); + } + setGraphicsConfiguration(cfg); + if(DEBUG_IMPLEMENTATION) { + System.err.println("BCEGL Window.windowCreated(): "+toHexString(cfgID)+", "+width+"x"+height+", "+cfg); + } + } + + private long windowHandleClose; +} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Display.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Display.java deleted file mode 100644 index 62af02abb..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Display.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.bcm.vc.iv; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; - -import jogamp.newt.DisplayImpl; -import jogamp.newt.NEWTJNILibLoader; -import jogamp.opengl.egl.EGL; -import jogamp.opengl.egl.EGLDisplayUtil; - -public class Display extends DisplayImpl { - static { - NEWTJNILibLoader.loadNEWT(); - - if (!Display.initIDs()) { - throw new NativeWindowException("Failed to initialize bcm.vc.iv Display jmethodIDs"); - } - if (!Screen.initIDs()) { - throw new NativeWindowException("Failed to initialize bcm.vc.iv Screen jmethodIDs"); - } - if (!Window.initIDs()) { - throw new NativeWindowException("Failed to initialize bcm.vc.iv Window jmethodIDs"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public Display() { - } - - protected void createNativeImpl() { - // FIXME: map name to EGL_*_DISPLAY - aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - } - - protected void closeNativeImpl() { - aDevice.close(); - } - - protected void dispatchMessagesNative() { - DispatchMessages(); - } - - protected static native boolean initIDs(); - private native void DispatchMessages(); -} - diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java new file mode 100644 index 000000000..08c5c573c --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java @@ -0,0 +1,78 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.bcm.vc.iv; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; + +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; +import jogamp.opengl.egl.EGL; +import jogamp.opengl.egl.EGLDisplayUtil; + +public class DisplayDriver extends DisplayImpl { + static { + NEWTJNILibLoader.loadNEWT(); + + if (!DisplayDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize bcm.vc.iv Display jmethodIDs"); + } + if (!ScreenDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize bcm.vc.iv Screen jmethodIDs"); + } + if (!WindowDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize bcm.vc.iv Window jmethodIDs"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + protected void createNativeImpl() { + // FIXME: map name to EGL_*_DISPLAY + aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + } + + protected void closeNativeImpl() { + aDevice.close(); + } + + protected void dispatchMessagesNative() { + DispatchMessages(); + } + + protected static native boolean initIDs(); + private native void DispatchMessages(); +} + diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Screen.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Screen.java deleted file mode 100644 index 484d4bf81..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Screen.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.bcm.vc.iv; - -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.ScreenImpl; - -public class Screen extends ScreenImpl { - static { - Display.initSingleton(); - } - - public Screen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - initNative(); - } - - protected void closeNativeImpl() { } - - protected int validateScreenIndex(int idx) { - return 0; // only one screen available - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); - } - - protected void setScreenSize(int width, int height) { - cachedWidth = width; - cachedHeight = height; - } - - private static int cachedWidth = 0; - private static int cachedHeight = 0; - - protected static native boolean initIDs(); - protected native void initNative(); -} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java new file mode 100644 index 000000000..787d1a1b4 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java @@ -0,0 +1,73 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.bcm.vc.iv; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.ScreenImpl; + +public class ScreenDriver extends ScreenImpl { + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + initNative(); + } + + protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(cachedWidth); + virtualSize.setHeight(cachedHeight); + } + + protected void setScreenSize(int width, int height) { + cachedWidth = width; + cachedHeight = height; + } + + private static int cachedWidth = 0; + private static int cachedHeight = 0; + + protected static native boolean initIDs(); + protected native void initNative(); +} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Window.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Window.java deleted file mode 100644 index 3d00949de..000000000 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/Window.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.newt.driver.bcm.vc.iv; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.WindowImpl; -import jogamp.newt.driver.linux.LinuxMouseTracker; - -public class Window extends WindowImpl { - private static final String WINDOW_CLASS_NAME = "NewtWindow"; - - static { - Display.initSingleton(); - } - - public Window() { - } - - protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new RuntimeException("Window parenting not supported (yet)"); - } - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - - nativeWindowHandle = CreateWindow(getWidth(), getHeight()); - if (nativeWindowHandle == 0) { - throw new NativeWindowException("Error creating egl window: "+cfg); - } - setVisible0(nativeWindowHandle, false); - setWindowHandle(nativeWindowHandle); - if (0 == getWindowHandle()) { - throw new NativeWindowException("Error native Window Handle is null"); - } - windowHandleClose = nativeWindowHandle; - addWindowListener(LinuxMouseTracker.getSingleton()); - focusChanged(false, true); - } - - protected void closeNativeImpl() { - removeWindowListener(LinuxMouseTracker.getSingleton()); - - if(0!=windowHandleClose) { - CloseWindow(windowHandleClose, windowUserData); - windowUserData=0; - } - } - - protected void requestFocusImpl(boolean reparented) { - focusChanged(false, true); - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - setVisible0(nativeWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags)); - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - if(0!=nativeWindowHandle) { - if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { - final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ; - setFullScreen0(nativeWindowHandle, fs); - if(fs) { - return true; - } - } - // int _x=(x>=0)?x:this.x; - // int _y=(x>=0)?y:this.y; - width=(width>0)?width:getWidth(); - height=(height>0)?height:getHeight(); - if(width>0 || height>0) { - setSize0(nativeWindowHandle, width, height); - } - if(x>=0 || y>=0) { - System.err.println("setPosition n/a in KD"); - } - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return new Point(x,y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop .. - } - - //---------------------------------------------------------------------- - // Internals only - // - - protected static native boolean initIDs(); - private native long CreateWindow(int width, int height); - private native long RealizeWindow(long eglWindowHandle); - private native int CloseWindow(long eglWindowHandle, long userData); - private native void setVisible0(long eglWindowHandle, boolean visible); - private native void setSize0(long eglWindowHandle, int width, int height); - private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); - - private void windowCreated(long userData) { - windowUserData=userData; - } - - private long nativeWindowHandle; - private long windowHandleClose; - private long windowUserData; -} diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java new file mode 100644 index 000000000..6d4f36964 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java @@ -0,0 +1,149 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.bcm.vc.iv; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.WindowImpl; +import jogamp.newt.driver.linux.LinuxMouseTracker; + +public class WindowDriver extends WindowImpl { + private static final String WINDOW_CLASS_NAME = "NewtWindow"; + + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + protected void createNativeImpl() { + if(0!=getParentWindowHandle()) { + throw new RuntimeException("Window parenting not supported (yet)"); + } + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + + nativeWindowHandle = CreateWindow(getWidth(), getHeight()); + if (nativeWindowHandle == 0) { + throw new NativeWindowException("Error creating egl window: "+cfg); + } + setVisible0(nativeWindowHandle, false); + setWindowHandle(nativeWindowHandle); + if (0 == getWindowHandle()) { + throw new NativeWindowException("Error native Window Handle is null"); + } + windowHandleClose = nativeWindowHandle; + addWindowListener(LinuxMouseTracker.getSingleton()); + focusChanged(false, true); + } + + protected void closeNativeImpl() { + removeWindowListener(LinuxMouseTracker.getSingleton()); + + if(0!=windowHandleClose) { + CloseWindow(windowHandleClose, windowUserData); + windowUserData=0; + } + } + + protected void requestFocusImpl(boolean reparented) { + focusChanged(false, true); + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + setVisible0(nativeWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags)); + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + if(0!=nativeWindowHandle) { + if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { + final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ; + setFullScreen0(nativeWindowHandle, fs); + if(fs) { + return true; + } + } + // int _x=(x>=0)?x:this.x; + // int _y=(x>=0)?y:this.y; + width=(width>0)?width:getWidth(); + height=(height>0)?height:getHeight(); + if(width>0 || height>0) { + setSize0(nativeWindowHandle, width, height); + } + if(x>=0 || y>=0) { + System.err.println("setPosition n/a in KD"); + } + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop .. + } + + //---------------------------------------------------------------------- + // Internals only + // + + protected static native boolean initIDs(); + private native long CreateWindow(int width, int height); + private native long RealizeWindow(long eglWindowHandle); + private native int CloseWindow(long eglWindowHandle, long userData); + private native void setVisible0(long eglWindowHandle, boolean visible); + private native void setSize0(long eglWindowHandle, int width, int height); + private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); + + private void windowCreated(long userData) { + windowUserData=userData; + } + + private long nativeWindowHandle; + private long windowHandleClose; + private long windowUserData; +} diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java deleted file mode 100644 index 20e151eb3..000000000 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.intel.gdl; - -import jogamp.newt.*; -import javax.media.nativewindow.*; - -public class Display extends jogamp.newt.DisplayImpl { - static int initCounter = 0; - - static { - NEWTJNILibLoader.loadNEWT(); - - if (!Screen.initIDs()) { - throw new NativeWindowException("Failed to initialize GDL Screen jmethodIDs"); - } - if (!Window.initIDs()) { - throw new NativeWindowException("Failed to initialize GDL Window jmethodIDs"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public Display() { - } - - protected void createNativeImpl() { - synchronized(Display.class) { - if(0==initCounter) { - displayHandle = CreateDisplay(); - if(0==displayHandle) { - throw new NativeWindowException("Couldn't initialize GDL Display"); - } - } - initCounter++; - } - aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle); - } - - protected void closeNativeImpl() { - if(0==displayHandle) { - throw new NativeWindowException("displayHandle null; initCnt "+initCounter); - } - synchronized(Display.class) { - if(initCounter>0) { - initCounter--; - if(0==initCounter) { - DestroyDisplay(displayHandle); - } - } - } - } - - protected void dispatchMessagesNative() { - if(0!=displayHandle) { - DispatchMessages(displayHandle, focusedWindow); - } - } - - protected void setFocus(Window focus) { - focusedWindow = focus; - } - - private long displayHandle = 0; - private Window focusedWindow = null; - private native long CreateDisplay(); - private native void DestroyDisplay(long displayHandle); - private native void DispatchMessages(long displayHandle, Window focusedWindow); -} - diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java new file mode 100644 index 000000000..97c384d33 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.intel.gdl; + +import jogamp.newt.*; +import javax.media.nativewindow.*; + +public class DisplayDriver extends jogamp.newt.DisplayImpl { + static int initCounter = 0; + + static { + NEWTJNILibLoader.loadNEWT(); + + if (!ScreenDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize GDL Screen jmethodIDs"); + } + if (!WindowDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize GDL Window jmethodIDs"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + protected void createNativeImpl() { + synchronized(DisplayDriver.class) { + if(0==initCounter) { + displayHandle = CreateDisplay(); + if(0==displayHandle) { + throw new NativeWindowException("Couldn't initialize GDL Display"); + } + } + initCounter++; + } + aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle); + } + + protected void closeNativeImpl() { + if(0==displayHandle) { + throw new NativeWindowException("displayHandle null; initCnt "+initCounter); + } + synchronized(DisplayDriver.class) { + if(initCounter>0) { + initCounter--; + if(0==initCounter) { + DestroyDisplay(displayHandle); + } + } + } + } + + protected void dispatchMessagesNative() { + if(0!=displayHandle) { + DispatchMessages(displayHandle, focusedWindow); + } + } + + protected void setFocus(WindowDriver focus) { + focusedWindow = focus; + } + + private long displayHandle = 0; + private WindowDriver focusedWindow = null; + private native long CreateDisplay(); + private native void DestroyDisplay(long displayHandle); + private native void DispatchMessages(long displayHandle, WindowDriver focusedWindow); +} + diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java deleted file mode 100644 index 66ad1c691..000000000 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.intel.gdl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -public class Screen extends jogamp.newt.ScreenImpl { - - static { - Display.initSingleton(); - } - - public Screen() { - } - - protected void createNativeImpl() { - AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice(); - GetScreenInfo(adevice.getHandle(), screen_idx); - aScreen = new DefaultGraphicsScreen(adevice, screen_idx); - } - - protected void closeNativeImpl() { } - - protected int validateScreenIndex(int idx) { - return 0; // only one screen available - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); - } - - //---------------------------------------------------------------------- - // Internals only - // - - protected static native boolean initIDs(); - private native void GetScreenInfo(long displayHandle, int screen_idx); - - // called by GetScreenInfo() .. - private void screenCreated(int width, int height) { - cachedWidth = width; - cachedHeight = height; - } - - private static int cachedWidth = 0; - private static int cachedHeight = 0; -} - diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java new file mode 100644 index 000000000..8eed14dde --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.intel.gdl; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +public class ScreenDriver extends jogamp.newt.ScreenImpl { + + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice(); + GetScreenInfo(adevice.getHandle(), screen_idx); + aScreen = new DefaultGraphicsScreen(adevice, screen_idx); + } + + protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(cachedWidth); + virtualSize.setHeight(cachedHeight); + } + + //---------------------------------------------------------------------- + // Internals only + // + + protected static native boolean initIDs(); + private native void GetScreenInfo(long displayHandle, int screen_idx); + + // called by GetScreenInfo() .. + private void screenCreated(int width, int height) { + cachedWidth = width; + cachedHeight = height; + } + + private static int cachedWidth = 0; + private static int cachedHeight = 0; +} + diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java deleted file mode 100644 index d5c75abd4..000000000 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.intel.gdl; - -import javax.media.nativewindow.*; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.Point; - -public class Window extends jogamp.newt.WindowImpl { - static { - Display.initSingleton(); - } - - public Window() { - } - - static long nextWindowHandle = 1; - - protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new NativeWindowException("GDL Window does not support window parenting"); - } - final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice(); - - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice, capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - - synchronized(Window.class) { - setWindowHandle(nextWindowHandle++); // just a marker - - surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), getX(), getY(), getWidth(), getHeight()); - if (surfaceHandle == 0) { - throw new NativeWindowException("Error creating window"); - } - } - } - - protected void closeNativeImpl() { - if(0!=surfaceHandle) { - synchronized(Window.class) { - CloseSurface(getDisplayHandle(), surfaceHandle); - } - surfaceHandle = 0; - ((Display)getScreen().getDisplay()).setFocus(null); - } - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - Screen screen = (Screen) getScreen(); - - if(width>screen.getWidth()) { - width=screen.getWidth(); - } - if(height>screen.getHeight()) { - height=screen.getHeight(); - } - if((x+width)>screen.getWidth()) { - x=screen.getWidth()-width; - } - if((y+height)>screen.getHeight()) { - y=screen.getHeight()-height; - } - - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, getScreen().getWidth(), getScreen().getHeight(), x, y, width, height); - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - if(0 != ( FLAG_IS_VISIBLE & flags)) { - ((Display)getScreen().getDisplay()).setFocus(this); - } - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - return true; - } - - protected void requestFocusImpl(boolean reparented) { - ((Display)getScreen().getDisplay()).setFocus(this); - } - - @Override - public final long getSurfaceHandle() { - return surfaceHandle; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return new Point(x,y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop .. - } - - //---------------------------------------------------------------------- - // Internals only - // - - protected static native boolean initIDs(); - private native long CreateSurface(long displayHandle, int scrn_width, int scrn_height, int x, int y, int width, int height); - private native void CloseSurface(long displayHandle, long surfaceHandle); - private native void SetBounds0(long surfaceHandle, int scrn_width, int scrn_height, int x, int y, int width, int height); - - private void updateBounds(int x, int y, int width, int height) { - definePosition(x, y); - defineSize(width, height); - } - - private long surfaceHandle; -} diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java new file mode 100644 index 000000000..98335f192 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.intel.gdl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; + +public class WindowDriver extends jogamp.newt.WindowImpl { + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + static long nextWindowHandle = 1; + + protected void createNativeImpl() { + if(0!=getParentWindowHandle()) { + throw new NativeWindowException("GDL Window does not support window parenting"); + } + final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice(); + + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice, capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + + synchronized(WindowDriver.class) { + setWindowHandle(nextWindowHandle++); // just a marker + + surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), getX(), getY(), getWidth(), getHeight()); + if (surfaceHandle == 0) { + throw new NativeWindowException("Error creating window"); + } + } + } + + protected void closeNativeImpl() { + if(0!=surfaceHandle) { + synchronized(WindowDriver.class) { + CloseSurface(getDisplayHandle(), surfaceHandle); + } + surfaceHandle = 0; + ((DisplayDriver)getScreen().getDisplay()).setFocus(null); + } + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + ScreenDriver screen = (ScreenDriver) getScreen(); + + if(width>screen.getWidth()) { + width=screen.getWidth(); + } + if(height>screen.getHeight()) { + height=screen.getHeight(); + } + if((x+width)>screen.getWidth()) { + x=screen.getWidth()-width; + } + if((y+height)>screen.getHeight()) { + y=screen.getHeight()-height; + } + + if(0!=surfaceHandle) { + SetBounds0(surfaceHandle, getScreen().getWidth(), getScreen().getHeight(), x, y, width, height); + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + if(0 != ( FLAG_IS_VISIBLE & flags)) { + ((DisplayDriver)getScreen().getDisplay()).setFocus(this); + } + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + return true; + } + + protected void requestFocusImpl(boolean reparented) { + ((DisplayDriver)getScreen().getDisplay()).setFocus(this); + } + + @Override + public final long getSurfaceHandle() { + return surfaceHandle; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop .. + } + + //---------------------------------------------------------------------- + // Internals only + // + + protected static native boolean initIDs(); + private native long CreateSurface(long displayHandle, int scrn_width, int scrn_height, int x, int y, int width, int height); + private native void CloseSurface(long displayHandle, long surfaceHandle); + private native void SetBounds0(long surfaceHandle, int scrn_width, int scrn_height, int x, int y, int width, int height); + + private void updateBounds(int x, int y, int width, int height) { + definePosition(x, y); + defineSize(width, height); + } + + private long surfaceHandle; +} diff --git a/src/newt/classes/jogamp/newt/driver/kd/Display.java b/src/newt/classes/jogamp/newt/driver/kd/Display.java deleted file mode 100644 index a58ad477a..000000000 --- a/src/newt/classes/jogamp/newt/driver/kd/Display.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.kd; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; - -import jogamp.newt.DisplayImpl; -import jogamp.newt.NEWTJNILibLoader; -import jogamp.opengl.egl.EGL; -import jogamp.opengl.egl.EGLDisplayUtil; - -public class Display extends DisplayImpl { - static { - NEWTJNILibLoader.loadNEWT(); - - if (!Window.initIDs()) { - throw new NativeWindowException("Failed to initialize kd.Window jmethodIDs"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public Display() { - } - - protected void createNativeImpl() { - // FIXME: map name to EGL_*_DISPLAY - aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - } - - protected void closeNativeImpl() { - aDevice.close(); - } - - protected void dispatchMessagesNative() { - DispatchMessages(); - } - - private native void DispatchMessages(); -} - diff --git a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java new file mode 100644 index 000000000..745be5dae --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.kd; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; + +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; +import jogamp.opengl.egl.EGL; +import jogamp.opengl.egl.EGLDisplayUtil; + +public class DisplayDriver extends DisplayImpl { + static { + NEWTJNILibLoader.loadNEWT(); + + if (!WindowDriver.initIDs()) { + throw new NativeWindowException("Failed to initialize kd.Window jmethodIDs"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + protected void createNativeImpl() { + // FIXME: map name to EGL_*_DISPLAY + aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + } + + protected void closeNativeImpl() { + aDevice.close(); + } + + protected void dispatchMessagesNative() { + DispatchMessages(); + } + + private native void DispatchMessages(); +} + diff --git a/src/newt/classes/jogamp/newt/driver/kd/Screen.java b/src/newt/classes/jogamp/newt/driver/kd/Screen.java deleted file mode 100644 index 53f5890b2..000000000 --- a/src/newt/classes/jogamp/newt/driver/kd/Screen.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.kd; - -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.ScreenImpl; - -public class Screen extends ScreenImpl { - static { - Display.initSingleton(); - } - - public Screen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { } - - protected int validateScreenIndex(int idx) { - return 0; // only one screen available - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); - } - - protected void sizeChanged(int w, int h) { - cachedWidth = w; - cachedHeight = h; - } - - private static int cachedWidth = 0; - private static int cachedHeight = 0; -} diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java new file mode 100644 index 000000000..656bcf5c9 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.kd; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.ScreenImpl; + +public class ScreenDriver extends ScreenImpl { + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(cachedWidth); + virtualSize.setHeight(cachedHeight); + } + + protected void sizeChanged(int w, int h) { + cachedWidth = w; + cachedHeight = h; + } + + private static int cachedWidth = 0; + private static int cachedHeight = 0; +} diff --git a/src/newt/classes/jogamp/newt/driver/kd/Window.java b/src/newt/classes/jogamp/newt/driver/kd/Window.java deleted file mode 100644 index ce65040c3..000000000 --- a/src/newt/classes/jogamp/newt/driver/kd/Window.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.kd; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.Point; -import javax.media.opengl.GLCapabilitiesImmutable; - -import jogamp.newt.WindowImpl; -import jogamp.opengl.egl.EGLGraphicsConfiguration; - -public class Window extends WindowImpl { - private static final String WINDOW_CLASS_NAME = "NewtWindow"; - - static { - Display.initSingleton(); - } - - public Window() { - } - - protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new RuntimeException("Window parenting not supported (yet)"); - } - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - - GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities(); - int eglConfigID = eglCaps.getVisualID(VIDType.EGL_CONFIG); - long eglConfig = EGLGraphicsConfiguration.EGLConfigId2EGLConfig(getDisplayHandle(), eglConfigID); - - eglWindowHandle = CreateWindow(getDisplayHandle(), eglConfig); - if (eglWindowHandle == 0) { - throw new NativeWindowException("Error creating egl window: "+cfg+", eglConfigID "+eglConfigID+", eglConfig 0x"+Long.toHexString(eglConfig)); - } - setVisible0(eglWindowHandle, false); - setWindowHandle(RealizeWindow(eglWindowHandle)); - if (0 == getWindowHandle()) { - throw new NativeWindowException("Error native Window Handle is null"); - } - windowHandleClose = eglWindowHandle; - } - - protected void closeNativeImpl() { - if(0!=windowHandleClose) { - CloseWindow(windowHandleClose, windowUserData); - windowUserData=0; - } - } - - protected void requestFocusImpl(boolean reparented) { } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - setVisible0(eglWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags)); - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - if(0!=eglWindowHandle) { - if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { - final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ; - setFullScreen0(eglWindowHandle, fs); - if(fs) { - return true; - } - } - // int _x=(x>=0)?x:this.x; - // int _y=(x>=0)?y:this.y; - width=(width>0)?width:getWidth(); - height=(height>0)?height:getHeight(); - if(width>0 || height>0) { - setSize0(eglWindowHandle, width, height); - } - if(x>=0 || y>=0) { - System.err.println("setPosition n/a in KD"); - } - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return new Point(x,y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop .. - } - - //---------------------------------------------------------------------- - // Internals only - // - - protected static native boolean initIDs(); - private native long CreateWindow(long displayHandle, long eglConfig); - private native long RealizeWindow(long eglWindowHandle); - private native int CloseWindow(long eglWindowHandle, long userData); - private native void setVisible0(long eglWindowHandle, boolean visible); - private native void setSize0(long eglWindowHandle, int width, int height); - private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); - - private void windowCreated(long userData) { - windowUserData=userData; - } - - @Override - protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(isFullscreen()) { - ((Screen)getScreen()).sizeChanged(getWidth(), getHeight()); - } - super.sizeChanged(defer, newWidth, newHeight, force); - } - - private long eglWindowHandle; - private long windowHandleClose; - private long windowUserData; -} diff --git a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java new file mode 100644 index 000000000..c733a3e94 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.kd; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.Point; +import javax.media.opengl.GLCapabilitiesImmutable; + +import jogamp.newt.WindowImpl; +import jogamp.opengl.egl.EGLGraphicsConfiguration; + +public class WindowDriver extends WindowImpl { + private static final String WINDOW_CLASS_NAME = "NewtWindow"; + + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + protected void createNativeImpl() { + if(0!=getParentWindowHandle()) { + throw new RuntimeException("Window parenting not supported (yet)"); + } + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + + GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities(); + int eglConfigID = eglCaps.getVisualID(VIDType.EGL_CONFIG); + long eglConfig = EGLGraphicsConfiguration.EGLConfigId2EGLConfig(getDisplayHandle(), eglConfigID); + + eglWindowHandle = CreateWindow(getDisplayHandle(), eglConfig); + if (eglWindowHandle == 0) { + throw new NativeWindowException("Error creating egl window: "+cfg+", eglConfigID "+eglConfigID+", eglConfig 0x"+Long.toHexString(eglConfig)); + } + setVisible0(eglWindowHandle, false); + setWindowHandle(RealizeWindow(eglWindowHandle)); + if (0 == getWindowHandle()) { + throw new NativeWindowException("Error native Window Handle is null"); + } + windowHandleClose = eglWindowHandle; + } + + protected void closeNativeImpl() { + if(0!=windowHandleClose) { + CloseWindow(windowHandleClose, windowUserData); + windowUserData=0; + } + } + + protected void requestFocusImpl(boolean reparented) { } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + setVisible0(eglWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags)); + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + if(0!=eglWindowHandle) { + if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) { + final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ; + setFullScreen0(eglWindowHandle, fs); + if(fs) { + return true; + } + } + // int _x=(x>=0)?x:this.x; + // int _y=(x>=0)?y:this.y; + width=(width>0)?width:getWidth(); + height=(height>0)?height:getHeight(); + if(width>0 || height>0) { + setSize0(eglWindowHandle, width, height); + } + if(x>=0 || y>=0) { + System.err.println("setPosition n/a in KD"); + } + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return new Point(x,y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop .. + } + + //---------------------------------------------------------------------- + // Internals only + // + + protected static native boolean initIDs(); + private native long CreateWindow(long displayHandle, long eglConfig); + private native long RealizeWindow(long eglWindowHandle); + private native int CloseWindow(long eglWindowHandle, long userData); + private native void setVisible0(long eglWindowHandle, boolean visible); + private native void setSize0(long eglWindowHandle, int width, int height); + private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); + + private void windowCreated(long userData) { + windowUserData=userData; + } + + @Override + protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { + if(isFullscreen()) { + ((ScreenDriver)getScreen()).sizeChanged(getWidth(), getHeight()); + } + super.sizeChanged(defer, newWidth, newHeight, force); + } + + private long eglWindowHandle; + private long windowHandleClose; + private long windowUserData; +} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java new file mode 100644 index 000000000..1a3f14859 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.macosx; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; + +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; + +public class DisplayDriver extends DisplayImpl { + static { + NEWTJNILibLoader.loadNEWT(); + + if(!initNSApplication0()) { + throw new NativeWindowException("Failed to initialize native Application hook"); + } + if(!WindowDriver.initIDs0()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + if(DEBUG) { + System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName()); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + public DisplayDriver() { + } + + protected void dispatchMessagesNative() { + // nop + } + + protected void createNativeImpl() { + aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + } + + protected void closeNativeImpl() { } + + public static void runNSApplication() { + runNSApplication0(); + } + public static void stopNSApplication() { + stopNSApplication0(); + } + + private static native boolean initNSApplication0(); + private static native void runNSApplication0(); + private static native void stopNSApplication0(); +} + diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java b/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java deleted file mode 100644 index 18f8d9538..000000000 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.macosx; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; - -import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; - -import jogamp.newt.DisplayImpl; -import jogamp.newt.NEWTJNILibLoader; - -public class MacDisplay extends DisplayImpl { - static { - NEWTJNILibLoader.loadNEWT(); - - if(!initNSApplication0()) { - throw new NativeWindowException("Failed to initialize native Application hook"); - } - if(!MacWindow.initIDs0()) { - throw new NativeWindowException("Failed to initialize jmethodIDs"); - } - if(DEBUG) { - System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName()); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - public MacDisplay() { - } - - protected void dispatchMessagesNative() { - // nop - } - - protected void createNativeImpl() { - aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); - } - - protected void closeNativeImpl() { } - - public static void runNSApplication() { - runNSApplication0(); - } - public static void stopNSApplication() { - stopNSApplication0(); - } - - private static native boolean initNSApplication0(); - private static native void runNSApplication0(); - private static native void stopNSApplication0(); -} - diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java index 46625f7a9..d39e0027b 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package jogamp.newt.driver.macosx; import com.jogamp.newt.event.KeyEvent; diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java deleted file mode 100644 index b9c725fd4..000000000 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.macosx; - -import java.util.List; - -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.ScreenImpl; - -import com.jogamp.common.util.IntObjectHashMap; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; - -public class MacScreen extends ScreenImpl { - - // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) - private static IntObjectHashMap/**/ scrnIdx2Dimension; - - static { - MacDisplay.initSingleton(); - scrnIdx2Dimension = new IntObjectHashMap(); - scrnIdx2Dimension.setKeyNotFoundValue(null); - } - - public MacScreen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { } - - private static native int getWidthImpl0(int scrn_idx); - private static native int getHeightImpl0(int scrn_idx); - - private int[] getScreenModeIdx(int idx) { - // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) - DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx); - if(null == dim) { - int[] res = getScreenSizeMM0(screen_idx); - if(null == res || 0 == res.length) { - return null; - } - dim = new Dimension(res[0], res[1]); - scrnIdx2Dimension.put(screen_idx, dim); - } - - int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight()); - if (null == modeProps || 0 == modeProps.length) { - return null; - } - if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { - throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); - } - return modeProps; - } - - private int nativeModeIdx; - - protected int[] getScreenModeFirstImpl() { - nativeModeIdx = 0; - return getScreenModeNextImpl(); - } - - protected int[] getScreenModeNextImpl() { - int[] modeProps = getScreenModeIdx(nativeModeIdx); - if (null != modeProps && 0 < modeProps.length) { - nativeModeIdx++; - return modeProps; - } - return null; - } - - protected ScreenMode getCurrentScreenModeImpl() { - int[] modeProps = getScreenModeIdx(-1); - if (null != modeProps && 0 < modeProps.length) { - return ScreenModeUtil.streamIn(modeProps, 0); - } - return null; - } - - protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { - final List screenModes = this.getScreenModesOrig(); - final int screenModeIdx = screenModes.indexOf(screenMode); - if(0>screenModeIdx) { - throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); - } - final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); - return setScreenMode0(screen_idx, nativeModeIdx); - } - - protected int validateScreenIndex(int idx) { - return idx; - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(getWidthImpl0(screen_idx)); - virtualSize.setHeight(getHeightImpl0(screen_idx)); - } - - private native int[] getScreenSizeMM0(int screen_idx); - private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM); - private native boolean setScreenMode0(int screen_index, int mode_idx); -} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java deleted file mode 100644 index 27d7a1679..000000000 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.macosx; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindow; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.MutableSurface; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.InsetsImmutable; -import javax.media.nativewindow.util.Point; -import javax.media.nativewindow.util.PointImmutable; - -import jogamp.newt.WindowImpl; -import jogamp.newt.driver.DriverClearFocus; -import jogamp.newt.driver.DriverUpdatePosition; - -import com.jogamp.newt.event.KeyEvent; - -public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { - - static { - MacDisplay.initSingleton(); - } - - public MacWindow() { - } - - @Override - protected void createNativeImpl() { - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true)); - if (0 == getWindowHandle()) { - throw new NativeWindowException("Error creating window"); - } - } - - @Override - protected void closeNativeImpl() { - try { - if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } - final long handle = getWindowHandle(); - setWindowHandle(0); - surfaceHandle = 0; - sscSurfaceHandle = 0; - isOffscreenInstance = false; - if (0 != handle) { - close0(handle); - } - } catch (Throwable t) { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t); - e.printStackTrace(); - } - } - } - - @Override - protected int lockSurfaceImpl() { - if(!isOffscreenInstance) { - return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; - } - return LOCK_SUCCESS; - } - - @Override - protected void unlockSurfaceImpl() { - if(!isOffscreenInstance) { - final long h = getWindowHandle(); - if(0 != h) { - unlockSurface0(h); - } - } - } - - @Override - public final long getSurfaceHandle() { - return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; - } - - public void setSurfaceHandle(long surfaceHandle) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); - } - sscSurfaceHandle = surfaceHandle; - if (isNativeValid()) { - if (0 != sscSurfaceHandle) { - orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); - } /** this is done by recreation! - else if (isVisible()){ - orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); - } */ - } - } - - @Override - protected void setTitleImpl(final String title) { - setTitle0(getWindowHandle(), title); - } - - protected void requestFocusImpl(boolean force) { - if(!isOffscreenInstance) { - requestFocus0(getWindowHandle(), force); - } else { - focusChanged(false, true); - } - } - - public final void clearFocus() { - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); - } - if(!isOffscreenInstance) { - resignFocus0(getWindowHandle()); - } else { - focusChanged(false, false); - } - } - - public void updatePosition() { - final Point pS = getTopLevelLocationOnScreen(getX(), getY()); - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS); - } - if( !isOffscreenInstance ) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); - } // else no offscreen position - // no native event (fullscreen, some reparenting) - super.positionChanged(true, getX(), getY()); - } - - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - final Point pS = getTopLevelLocationOnScreen(x, y); - isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); - - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ - ", offscreenInstance "+isOffscreenInstance+ - ", "+getReconfigureFlagsAsString(null, flags)); - } - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { - if ( !isOffscreenInstance ) { - orderOut0(getWindowHandle()); - } - // no native event .. - visibleChanged(true, false); - } - if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) || - 0 != ( FLAG_CHANGE_DECORATION & flags) || - 0 != ( FLAG_CHANGE_PARENTING & flags) || - 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } - } - if(x>=0 && y>=0) { - if( !isOffscreenInstance ) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); - } // else no offscreen position - // no native event (fullscreen, some reparenting) - super.positionChanged(true, x, y); - } - if(width>0 && height>0) { - if( !isOffscreenInstance ) { - setContentSize0(getWindowHandle(), width, height); - } // else offscreen size is realized via recreation - // no native event (fullscreen, some reparenting) - sizeChanged(true, width, height, false); // incl. validation (incl. repositioning) - } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { - if( !isOffscreenInstance ) { - orderFront0(getWindowHandle()); - } - // no native event .. - visibleChanged(true, true); - } - if( !isOffscreenInstance ) { - setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); - } - return true; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - Point p = new Point(x, y); - // min val is 0 - p.setX(Math.max(p.getX(), 0)); - p.setY(Math.max(p.getY(), 0)); - - final NativeWindow parent = getParent(); - if( null != parent && 0 != parent.getWindowHandle() ) { - p.translate(parent.getLocationOnScreen(null)); - } - return p; - } - - private Point getTopLevelLocationOnScreen(int x, int y) { - final InsetsImmutable _insets = getInsets(); // zero if undecorated - // client position -> top-level window position - x -= _insets.getLeftWidth() ; - y -= _insets.getTopHeight() ; - return getLocationOnScreenImpl(x, y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop - using event driven insetsChange(..) - } - - @Override - protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(getWidth() != newWidth || getHeight() != newHeight) { - final Point p0S = getTopLevelLocationOnScreen(getX(), getY()); - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); - } - super.sizeChanged(defer, newWidth, newHeight, force); - } - - @Override - protected void positionChanged(boolean defer, int newX, int newY) { - // passed coordinates are in screen position of the client area - if(getWindowHandle()!=0) { - // screen position -> window position - Point absPos = new Point(newX, newY); - final NativeWindow parent = getParent(); - if(null != parent) { - absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); - } - super.positionChanged(defer, absPos.getX(), absPos.getY()); - } - } - - @Override - protected boolean setPointerVisibleImpl(final boolean pointerVisible) { - if( !isOffscreenInstance ) { - return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible); - } // else may need offscreen solution ? FIXME - return false; - } - - @Override - protected boolean confinePointerImpl(final boolean confine) { - if( !isOffscreenInstance ) { - return confinePointer0(getWindowHandle(), confine); - } // else may need offscreen solution ? FIXME - return false; - } - - @Override - protected void warpPointerImpl(final int x, final int y) { - if( !isOffscreenInstance ) { - warpPointer0(getWindowHandle(), x, y); - } // else may need offscreen solution ? FIXME - } - - @Override - public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - // Note that we send the key char for the key code on this - // platform -- we do not get any useful key codes out of the system - final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); - if(valid) { - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); - } - } - - @Override - public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { - // Note that we send the key char for the key code on this - // platform -- we do not get any useful key codes out of the system - final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); - if(valid) { - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); - } - } - - private int keyDownModifiers = 0; - private int keyDownCode = 0; - - private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) { - switch(eventType) { - case KeyEvent.EVENT_KEY_PRESSED: - keyDownModifiers = modifiers; - keyDownCode = keyCode; - return true; - case KeyEvent.EVENT_KEY_RELEASED: - return keyDownModifiers == modifiers && keyDownCode == keyCode; - case KeyEvent.EVENT_KEY_TYPED: - final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode; - keyDownModifiers = 0; - keyDownCode = 0; - return matchKeyDown; - default: - throw new NativeWindowException("Unexpected key event type " + eventType); - } - } - - - //---------------------------------------------------------------------- - // Internals only - // - - private void createWindow(final boolean offscreenInstance, final boolean recreate, - final PointImmutable pS, final int width, final int height, - final boolean fullscreen) { - - if(0!=getWindowHandle() && !recreate) { - return; - } - - try { - if(0!=getWindowHandle()) { - // save the view .. close the window - surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0); - if(recreate && 0==surfaceHandle) { - throw new NativeWindowException("Internal Error - recreate, window but no view"); - } - close0(getWindowHandle()); - setWindowHandle(0); - } else { - surfaceHandle = 0; - } - setWindowHandle(createWindow0(getParentWindowHandle(), - pS.getX(), pS.getY(), width, height, - (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), - fullscreen, - ((isUndecorated() || offscreenInstance) ? - NSBorderlessWindowMask : - NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), - NSBackingStoreBuffered, - getScreen().getIndex(), surfaceHandle)); - if (getWindowHandle() == 0) { - throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); - } - surfaceHandle = contentView0(getWindowHandle()); - if( offscreenInstance ) { - orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle()); - } else { - setTitle0(getWindowHandle(), getTitle()); - } - } catch (Exception ie) { - ie.printStackTrace(); - } - } - - protected static native boolean initIDs0(); - private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, int windowStyle, - int backingStoreType, - int screen_idx, long view); - private native boolean lockSurface0(long window); - private native void unlockSurface0(long window); - private native void requestFocus0(long window, boolean force); - private native void resignFocus0(long window); - /** in case of a child window, it actually only issues orderBack(..) */ - private native void orderOut0(long window); - private native void orderFront0(long window); - private native void close0(long window); - private native void setTitle0(long window, String title); - private native long contentView0(long window); - private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); - private native void setContentSize0(long window, int w, int h); - private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); - private native void setAlwaysOnTop0(long window, boolean atop); - private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); - private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); - private static native boolean confinePointer0(long windowHandle, boolean confine); - private static native void warpPointer0(long windowHandle, int x, int y); - - // Window styles - private static final int NSBorderlessWindowMask = 0; - private static final int NSTitledWindowMask = 1 << 0; - private static final int NSClosableWindowMask = 1 << 1; - private static final int NSMiniaturizableWindowMask = 1 << 2; - private static final int NSResizableWindowMask = 1 << 3; - - // Window backing store types - private static final int NSBackingStoreRetained = 0; - private static final int NSBackingStoreNonretained = 1; - private static final int NSBackingStoreBuffered = 2; - - private volatile long surfaceHandle = 0; - private long sscSurfaceHandle = 0; - private boolean isOffscreenInstance = false; - -} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java new file mode 100644 index 000000000..24e60ba0a --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.macosx; + +import java.util.List; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.ScreenImpl; + +import com.jogamp.common.util.IntObjectHashMap; +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; + +public class ScreenDriver extends ScreenImpl { + + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + private static IntObjectHashMap/**/ scrnIdx2Dimension; + + static { + DisplayDriver.initSingleton(); + scrnIdx2Dimension = new IntObjectHashMap(); + scrnIdx2Dimension.setKeyNotFoundValue(null); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { } + + private static native int getWidthImpl0(int scrn_idx); + private static native int getHeightImpl0(int scrn_idx); + + private int[] getScreenModeIdx(int idx) { + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx); + if(null == dim) { + int[] res = getScreenSizeMM0(screen_idx); + if(null == res || 0 == res.length) { + return null; + } + dim = new Dimension(res[0], res[1]); + scrnIdx2Dimension.put(screen_idx, dim); + } + + int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight()); + if (null == modeProps || 0 == modeProps.length) { + return null; + } + if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { + throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); + } + return modeProps; + } + + private int nativeModeIdx; + + protected int[] getScreenModeFirstImpl() { + nativeModeIdx = 0; + return getScreenModeNextImpl(); + } + + protected int[] getScreenModeNextImpl() { + int[] modeProps = getScreenModeIdx(nativeModeIdx); + if (null != modeProps && 0 < modeProps.length) { + nativeModeIdx++; + return modeProps; + } + return null; + } + + protected ScreenMode getCurrentScreenModeImpl() { + int[] modeProps = getScreenModeIdx(-1); + if (null != modeProps && 0 < modeProps.length) { + return ScreenModeUtil.streamIn(modeProps, 0); + } + return null; + } + + protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { + final List screenModes = this.getScreenModesOrig(); + final int screenModeIdx = screenModes.indexOf(screenMode); + if(0>screenModeIdx) { + throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); + } + final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); + return setScreenMode0(screen_idx, nativeModeIdx); + } + + protected int validateScreenIndex(int idx) { + return idx; + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(getWidthImpl0(screen_idx)); + virtualSize.setHeight(getHeightImpl0(screen_idx)); + } + + private native int[] getScreenSizeMM0(int screen_idx); + private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM); + private native boolean setScreenMode0(int screen_index, int mode_idx); +} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java new file mode 100644 index 000000000..ea48569bf --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.macosx; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; + +import jogamp.newt.WindowImpl; +import jogamp.newt.driver.DriverClearFocus; +import jogamp.newt.driver.DriverUpdatePosition; + +import com.jogamp.newt.event.KeyEvent; + +public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { + + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + @Override + protected void createNativeImpl() { + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true)); + if (0 == getWindowHandle()) { + throw new NativeWindowException("Error creating window"); + } + } + + @Override + protected void closeNativeImpl() { + try { + if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } + final long handle = getWindowHandle(); + setWindowHandle(0); + surfaceHandle = 0; + sscSurfaceHandle = 0; + isOffscreenInstance = false; + if (0 != handle) { + close0(handle); + } + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } + } + + @Override + protected int lockSurfaceImpl() { + if(!isOffscreenInstance) { + return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; + } + return LOCK_SUCCESS; + } + + @Override + protected void unlockSurfaceImpl() { + if(!isOffscreenInstance) { + final long h = getWindowHandle(); + if(0 != h) { + unlockSurface0(h); + } + } + } + + @Override + public final long getSurfaceHandle() { + return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; + } + + public void setSurfaceHandle(long surfaceHandle) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); + } + sscSurfaceHandle = surfaceHandle; + if (isNativeValid()) { + if (0 != sscSurfaceHandle) { + orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } /** this is done by recreation! + else if (isVisible()){ + orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } */ + } + } + + @Override + protected void setTitleImpl(final String title) { + setTitle0(getWindowHandle(), title); + } + + protected void requestFocusImpl(boolean force) { + if(!isOffscreenInstance) { + requestFocus0(getWindowHandle(), force); + } else { + focusChanged(false, true); + } + } + + public final void clearFocus() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); + } + if(!isOffscreenInstance) { + resignFocus0(getWindowHandle()); + } else { + focusChanged(false, false); + } + } + + public void updatePosition() { + final Point pS = getTopLevelLocationOnScreen(getX(), getY()); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS); + } + if( !isOffscreenInstance ) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); + } // else no offscreen position + // no native event (fullscreen, some reparenting) + super.positionChanged(true, getX(), getY()); + } + + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + final Point pS = getTopLevelLocationOnScreen(x, y); + isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); + + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ + ", offscreenInstance "+isOffscreenInstance+ + ", "+getReconfigureFlagsAsString(null, flags)); + } + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { + if ( !isOffscreenInstance ) { + orderOut0(getWindowHandle()); + } + // no native event .. + visibleChanged(true, false); + } + if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) || + 0 != ( FLAG_CHANGE_DECORATION & flags) || + 0 != ( FLAG_CHANGE_PARENTING & flags) || + 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { + createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } + } + if(x>=0 && y>=0) { + if( !isOffscreenInstance ) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); + } // else no offscreen position + // no native event (fullscreen, some reparenting) + super.positionChanged(true, x, y); + } + if(width>0 && height>0) { + if( !isOffscreenInstance ) { + setContentSize0(getWindowHandle(), width, height); + } // else offscreen size is realized via recreation + // no native event (fullscreen, some reparenting) + sizeChanged(true, width, height, false); // incl. validation (incl. repositioning) + } + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { + if( !isOffscreenInstance ) { + orderFront0(getWindowHandle()); + } + // no native event .. + visibleChanged(true, true); + } + if( !isOffscreenInstance ) { + setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); + } + return true; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + Point p = new Point(x, y); + // min val is 0 + p.setX(Math.max(p.getX(), 0)); + p.setY(Math.max(p.getY(), 0)); + + final NativeWindow parent = getParent(); + if( null != parent && 0 != parent.getWindowHandle() ) { + p.translate(parent.getLocationOnScreen(null)); + } + return p; + } + + private Point getTopLevelLocationOnScreen(int x, int y) { + final InsetsImmutable _insets = getInsets(); // zero if undecorated + // client position -> top-level window position + x -= _insets.getLeftWidth() ; + y -= _insets.getTopHeight() ; + return getLocationOnScreenImpl(x, y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop - using event driven insetsChange(..) + } + + @Override + protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { + if(getWidth() != newWidth || getHeight() != newHeight) { + final Point p0S = getTopLevelLocationOnScreen(getX(), getY()); + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); + } + super.sizeChanged(defer, newWidth, newHeight, force); + } + + @Override + protected void positionChanged(boolean defer, int newX, int newY) { + // passed coordinates are in screen position of the client area + if(getWindowHandle()!=0) { + // screen position -> window position + Point absPos = new Point(newX, newY); + final NativeWindow parent = getParent(); + if(null != parent) { + absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); + } + super.positionChanged(defer, absPos.getX(), absPos.getY()); + } + } + + @Override + protected boolean setPointerVisibleImpl(final boolean pointerVisible) { + if( !isOffscreenInstance ) { + return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible); + } // else may need offscreen solution ? FIXME + return false; + } + + @Override + protected boolean confinePointerImpl(final boolean confine) { + if( !isOffscreenInstance ) { + return confinePointer0(getWindowHandle(), confine); + } // else may need offscreen solution ? FIXME + return false; + } + + @Override + protected void warpPointerImpl(final int x, final int y) { + if( !isOffscreenInstance ) { + warpPointer0(getWindowHandle(), x, y); + } // else may need offscreen solution ? FIXME + } + + @Override + public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we send the key char for the key code on this + // platform -- we do not get any useful key codes out of the system + final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); + } + } + + @Override + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we send the key char for the key code on this + // platform -- we do not get any useful key codes out of the system + final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); + } + } + + private int keyDownModifiers = 0; + private int keyDownCode = 0; + + private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) { + switch(eventType) { + case KeyEvent.EVENT_KEY_PRESSED: + keyDownModifiers = modifiers; + keyDownCode = keyCode; + return true; + case KeyEvent.EVENT_KEY_RELEASED: + return keyDownModifiers == modifiers && keyDownCode == keyCode; + case KeyEvent.EVENT_KEY_TYPED: + final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode; + keyDownModifiers = 0; + keyDownCode = 0; + return matchKeyDown; + default: + throw new NativeWindowException("Unexpected key event type " + eventType); + } + } + + + //---------------------------------------------------------------------- + // Internals only + // + + private void createWindow(final boolean offscreenInstance, final boolean recreate, + final PointImmutable pS, final int width, final int height, + final boolean fullscreen) { + + if(0!=getWindowHandle() && !recreate) { + return; + } + + try { + if(0!=getWindowHandle()) { + // save the view .. close the window + surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0); + if(recreate && 0==surfaceHandle) { + throw new NativeWindowException("Internal Error - recreate, window but no view"); + } + close0(getWindowHandle()); + setWindowHandle(0); + } else { + surfaceHandle = 0; + } + setWindowHandle(createWindow0(getParentWindowHandle(), + pS.getX(), pS.getY(), width, height, + (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), + fullscreen, + ((isUndecorated() || offscreenInstance) ? + NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), + NSBackingStoreBuffered, + getScreen().getIndex(), surfaceHandle)); + if (getWindowHandle() == 0) { + throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); + } + surfaceHandle = contentView0(getWindowHandle()); + if( offscreenInstance ) { + orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle()); + } else { + setTitle0(getWindowHandle(), getTitle()); + } + } catch (Exception ie) { + ie.printStackTrace(); + } + } + + protected static native boolean initIDs0(); + private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, + boolean opaque, boolean fullscreen, int windowStyle, + int backingStoreType, + int screen_idx, long view); + private native boolean lockSurface0(long window); + private native void unlockSurface0(long window); + private native void requestFocus0(long window, boolean force); + private native void resignFocus0(long window); + /** in case of a child window, it actually only issues orderBack(..) */ + private native void orderOut0(long window); + private native void orderFront0(long window); + private native void close0(long window); + private native void setTitle0(long window, String title); + private native long contentView0(long window); + private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); + private native void setContentSize0(long window, int w, int h); + private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); + private native void setAlwaysOnTop0(long window, boolean atop); + private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); + private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); + private static native boolean confinePointer0(long windowHandle, boolean confine); + private static native void warpPointer0(long windowHandle, int x, int y); + + // Window styles + private static final int NSBorderlessWindowMask = 0; + private static final int NSTitledWindowMask = 1 << 0; + private static final int NSClosableWindowMask = 1 << 1; + private static final int NSMiniaturizableWindowMask = 1 << 2; + private static final int NSResizableWindowMask = 1 << 3; + + // Window backing store types + private static final int NSBackingStoreRetained = 0; + private static final int NSBackingStoreNonretained = 1; + private static final int NSBackingStoreBuffered = 2; + + private volatile long surfaceHandle = 0; + private long sscSurfaceHandle = 0; + private boolean isOffscreenInstance = false; + +} diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java new file mode 100644 index 000000000..579ec5be8 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.windows; + +import jogamp.nativewindow.windows.RegisteredClass; +import jogamp.nativewindow.windows.RegisteredClassFactory; +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; + +public class DisplayDriver extends DisplayImpl { + + private static final String newtClassBaseName = "_newt_clazz" ; + private static RegisteredClassFactory sharedClassFactory; + + static { + NEWTJNILibLoader.loadNEWT(); + + if (!WindowDriver.initIDs0()) { + throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs"); + } + sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0()); + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + private RegisteredClass sharedClass; + + public DisplayDriver() { + } + + protected void createNativeImpl() { + sharedClass = sharedClassFactory.getSharedClass(); + aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + } + + protected void closeNativeImpl() { + sharedClassFactory.releaseSharedClass(); + } + + protected void dispatchMessagesNative() { + DispatchMessages0(); + } + + protected long getHInstance() { + return sharedClass.getHandle(); + } + + protected String getWindowClassName() { + return sharedClass.getName(); + } + + //---------------------------------------------------------------------- + // Internals only + // + private static native void DispatchMessages0(); +} + diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java new file mode 100644 index 000000000..948b29460 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ +package jogamp.newt.driver.windows; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import jogamp.newt.ScreenImpl; + +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; + +public class ScreenDriver extends ScreenImpl { + + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { + } + + private int[] getScreenModeIdx(int idx) { + int[] modeProps = getScreenMode0(screen_idx, idx); + if (null == modeProps || 0 == modeProps.length) { + return null; + } + if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { + throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); + } + return modeProps; + } + + private int nativeModeIdx; + + protected int[] getScreenModeFirstImpl() { + nativeModeIdx = 0; + return getScreenModeNextImpl(); + } + + protected int[] getScreenModeNextImpl() { + int[] modeProps = getScreenModeIdx(nativeModeIdx); + if (null != modeProps && 0 < modeProps.length) { + nativeModeIdx++; + return modeProps; + } + return null; + } + + protected ScreenMode getCurrentScreenModeImpl() { + int[] modeProps = getScreenModeIdx(-1); + if (null != modeProps && 0 < modeProps.length) { + return ScreenModeUtil.streamIn(modeProps, 0); + } + return null; + } + + protected boolean setCurrentScreenModeImpl(ScreenMode sm) { + return setScreenMode0(screen_idx, + sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(), + sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(), + sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(), + sm.getMonitorMode().getRefreshRate(), + sm.getRotation()); + } + + protected int validateScreenIndex(int idx) { + return 0; // big-desktop, only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(getOriginX0(screen_idx)); + virtualOrigin.setY(getOriginY0(screen_idx)); + virtualSize.setWidth(getWidthImpl0(screen_idx)); + virtualSize.setHeight(getHeightImpl0(screen_idx)); + } + + // Native calls + private native int getOriginX0(int screen_idx); + private native int getOriginY0(int screen_idx); + private native int getWidthImpl0(int scrn_idx); + private native int getHeightImpl0(int scrn_idx); + + private native int[] getScreenMode0(int screen_index, int mode_index); + private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot); +} diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java new file mode 100644 index 000000000..39ea54575 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.windows; + +import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; +import jogamp.newt.WindowImpl; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.Point; + +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; + +public class WindowDriver extends WindowImpl { + + private long hmon; + private long hdc; + private long hdc_old; + private long windowHandleClose; + + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + @Override + protected int lockSurfaceImpl() { + if (0 != hdc) { + throw new InternalError("surface not released"); + } + hdc = GDI.GetDC(getWindowHandle()); + hmon = MonitorFromWindow0(getWindowHandle()); + + // return ( 0 == hdc ) ? LOCK_SURFACE_NOT_READY : ( hdc_old != hdc ) ? LOCK_SURFACE_CHANGED : LOCK_SUCCESS ; + if( 0 == hdc ) { + return LOCK_SURFACE_NOT_READY; + } + if( hdc_old == hdc ) { + return LOCK_SUCCESS; + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc)); + // Thread.dumpStack(); + } + return LOCK_SURFACE_CHANGED; + } + + @Override + protected void unlockSurfaceImpl() { + if (0 != hdc) { + GDI.ReleaseDC(getWindowHandle(), hdc); + hdc_old = hdc; + hdc=0; + } + } + + @Override + public final long getSurfaceHandle() { + return hdc; + } + + @Override + public boolean hasDeviceChanged() { + if(0!=getWindowHandle()) { + long _hmon = MonitorFromWindow0(getWindowHandle()); + if (hmon != _hmon) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Info: Window Device Changed "+Thread.currentThread().getName()+ + ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon)); + // Thread.dumpStack(); + } + hmon = _hmon; + return true; + } + } + return false; + } + + protected void createNativeImpl() { + final ScreenDriver screen = (ScreenDriver) getScreen(); + final DisplayDriver display = (DisplayDriver) screen.getDisplay(); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + setGraphicsConfiguration(cfg); + final int flags = getReconfigureFlags(0, true) & + ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; + setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(), + getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); + if (getWindowHandle() == 0) { + throw new NativeWindowException("Error creating window"); + } + windowHandleClose = getWindowHandle(); + addMouseListener(new MouseTracker()); + + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+ + " (Parent HWND "+toHexString(getParentWindowHandle())+ + ") : HWND "+toHexString(getWindowHandle())+", "+Thread.currentThread()); + e.printStackTrace(); + } + } + + class MouseTracker extends MouseAdapter { + public void mouseEntered(MouseEvent e) { + WindowDriver.trackPointerLeave0(WindowDriver.this.getWindowHandle()); + } + } + + protected void closeNativeImpl() { + if(windowHandleClose != 0) { + if (hdc != 0) { + try { + GDI.ReleaseDC(windowHandleClose, hdc); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } + } + try { + GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent + GDI.DestroyWindow(windowHandleClose); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + } + } + hdc = 0; + hdc_old = 0; + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("WindowsWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ + getReconfigureFlagsAsString(null, flags)); + } + + if(0 == ( FLAG_IS_UNDECORATED & flags)) { + final InsetsImmutable i = getInsets(); + + // client position -> top-level window position + x -= i.getLeftWidth() ; + y -= i.getTopHeight() ; + + if(0 top-level window size + width += i.getTotalWidth(); + height += i.getTotalHeight(); + } + } + reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags); + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } + return true; + } + + protected void requestFocusImpl(boolean force) { + requestFocus0(getWindowHandle(), force); + } + + @Override + protected void setTitleImpl(final String title) { + setTitle0(getWindowHandle(), title); + } + + @Override + protected boolean setPointerVisibleImpl(final boolean pointerVisible) { + final Boolean[] res = new Boolean[] { Boolean.FALSE }; + + this.runOnEDTIfAvail(true, new Runnable() { + public void run() { + res[0] = Boolean.valueOf(setPointerVisible0(getWindowHandle(), pointerVisible)); + } + }); + return res[0].booleanValue(); + } + + @Override + protected boolean confinePointerImpl(final boolean confine) { + final Boolean[] res = new Boolean[] { Boolean.FALSE }; + + this.runOnEDTIfAvail(true, new Runnable() { + public void run() { + final Point p0 = getLocationOnScreenImpl(0, 0); + res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine, + p0.getX(), p0.getY(), p0.getX()+getWidth(), p0.getY()+getHeight())); + } + }); + return res[0].booleanValue(); + } + + @Override + protected void warpPointerImpl(final int x, final int y) { + this.runOnEDTIfAvail(true, new Runnable() { + public void run() { + final Point sPos = getLocationOnScreenImpl(x, y); + warpPointer0(getWindowHandle(), sPos.getX(), sPos.getY()); + } + }); + return; + } + + protected Point getLocationOnScreenImpl(int x, int y) { + return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop - using event driven insetsChange(..) + } + + private final int validateKeyCode(int eventType, int keyCode) { + switch(eventType) { + case KeyEvent.EVENT_KEY_PRESSED: + lastPressedKeyCode = keyCode; + break; + case KeyEvent.EVENT_KEY_TYPED: + if(-1==keyCode) { + keyCode = lastPressedKeyCode; + } + lastPressedKeyCode = -1; + break; + } + return keyCode; + } + private int lastPressedKeyCode = 0; + + @Override + public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform + keyCode = validateKeyCode(eventType, keyCode); + super.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + } + + @Override + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform + keyCode = validateKeyCode(eventType, keyCode); + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar); + } + + //---------------------------------------------------------------------- + // Internals only + // + protected static native boolean initIDs0(); + protected static native long getNewtWndProc0(); + + private native long CreateWindow0(long hInstance, String wndClassName, String wndName, + long parentWindowHandle, + int x, int y, int width, int height, boolean autoPosition, int flags); + private native long MonitorFromWindow0(long windowHandle); + private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, + int x, int y, int width, int height, int flags); + private static native void setTitle0(long windowHandle, String title); + private native void requestFocus0(long windowHandle, boolean force); + + private static native boolean setPointerVisible0(long windowHandle, boolean visible); + private static native boolean confinePointer0(long windowHandle, boolean grab, int l, int t, int r, int b); + private static native void warpPointer0(long windowHandle, int x, int y); + private static native void trackPointerLeave0(long windowHandle); +} diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java deleted file mode 100644 index 225b115e4..000000000 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.windows; - -import jogamp.nativewindow.windows.RegisteredClass; -import jogamp.nativewindow.windows.RegisteredClassFactory; -import jogamp.newt.DisplayImpl; -import jogamp.newt.NEWTJNILibLoader; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; - -import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; - -public class WindowsDisplay extends DisplayImpl { - - private static final String newtClassBaseName = "_newt_clazz" ; - private static RegisteredClassFactory sharedClassFactory; - - static { - NEWTJNILibLoader.loadNEWT(); - - if (!WindowsWindow.initIDs0()) { - throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs"); - } - sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowsWindow.getNewtWndProc0()); - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - private RegisteredClass sharedClass; - - public WindowsDisplay() { - } - - protected void createNativeImpl() { - sharedClass = sharedClassFactory.getSharedClass(); - aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); - } - - protected void closeNativeImpl() { - sharedClassFactory.releaseSharedClass(); - } - - protected void dispatchMessagesNative() { - DispatchMessages0(); - } - - protected long getHInstance() { - return sharedClass.getHandle(); - } - - protected String getWindowClassName() { - return sharedClass.getName(); - } - - //---------------------------------------------------------------------- - // Internals only - // - private static native void DispatchMessages0(); -} - diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java deleted file mode 100644 index f8bce9da3..000000000 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ -package jogamp.newt.driver.windows; - -import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import jogamp.newt.ScreenImpl; - -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; - -public class WindowsScreen extends ScreenImpl { - - static { - WindowsDisplay.initSingleton(); - } - - public WindowsScreen() { - } - - protected void createNativeImpl() { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { - } - - private int[] getScreenModeIdx(int idx) { - int[] modeProps = getScreenMode0(screen_idx, idx); - if (null == modeProps || 0 == modeProps.length) { - return null; - } - if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { - throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); - } - return modeProps; - } - - private int nativeModeIdx; - - protected int[] getScreenModeFirstImpl() { - nativeModeIdx = 0; - return getScreenModeNextImpl(); - } - - protected int[] getScreenModeNextImpl() { - int[] modeProps = getScreenModeIdx(nativeModeIdx); - if (null != modeProps && 0 < modeProps.length) { - nativeModeIdx++; - return modeProps; - } - return null; - } - - protected ScreenMode getCurrentScreenModeImpl() { - int[] modeProps = getScreenModeIdx(-1); - if (null != modeProps && 0 < modeProps.length) { - return ScreenModeUtil.streamIn(modeProps, 0); - } - return null; - } - - protected boolean setCurrentScreenModeImpl(ScreenMode sm) { - return setScreenMode0(screen_idx, - sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(), - sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(), - sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(), - sm.getMonitorMode().getRefreshRate(), - sm.getRotation()); - } - - protected int validateScreenIndex(int idx) { - return 0; // big-desktop, only one screen available - } - - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(getOriginX0(screen_idx)); - virtualOrigin.setY(getOriginY0(screen_idx)); - virtualSize.setWidth(getWidthImpl0(screen_idx)); - virtualSize.setHeight(getHeightImpl0(screen_idx)); - } - - // Native calls - private native int getOriginX0(int screen_idx); - private native int getOriginY0(int screen_idx); - private native int getWidthImpl0(int scrn_idx); - private native int getHeightImpl0(int scrn_idx); - - private native int[] getScreenMode0(int screen_index, int mode_index); - private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot); -} diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java deleted file mode 100644 index 6a8c81f3d..000000000 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.windows; - -import jogamp.nativewindow.windows.GDI; -import jogamp.nativewindow.windows.GDIUtil; -import jogamp.newt.WindowImpl; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.InsetsImmutable; -import javax.media.nativewindow.util.Point; - -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.MouseAdapter; -import com.jogamp.newt.event.MouseEvent; - -public class WindowsWindow extends WindowImpl { - - private long hmon; - private long hdc; - private long hdc_old; - private long windowHandleClose; - - static { - WindowsDisplay.initSingleton(); - } - - public WindowsWindow() { - } - - @Override - protected int lockSurfaceImpl() { - if (0 != hdc) { - throw new InternalError("surface not released"); - } - hdc = GDI.GetDC(getWindowHandle()); - hmon = MonitorFromWindow0(getWindowHandle()); - - // return ( 0 == hdc ) ? LOCK_SURFACE_NOT_READY : ( hdc_old != hdc ) ? LOCK_SURFACE_CHANGED : LOCK_SUCCESS ; - if( 0 == hdc ) { - return LOCK_SURFACE_NOT_READY; - } - if( hdc_old == hdc ) { - return LOCK_SUCCESS; - } - if(DEBUG_IMPLEMENTATION) { - System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc)); - // Thread.dumpStack(); - } - return LOCK_SURFACE_CHANGED; - } - - @Override - protected void unlockSurfaceImpl() { - if (0 != hdc) { - GDI.ReleaseDC(getWindowHandle(), hdc); - hdc_old = hdc; - hdc=0; - } - } - - @Override - public final long getSurfaceHandle() { - return hdc; - } - - @Override - public boolean hasDeviceChanged() { - if(0!=getWindowHandle()) { - long _hmon = MonitorFromWindow0(getWindowHandle()); - if (hmon != _hmon) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("Info: Window Device Changed "+Thread.currentThread().getName()+ - ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon)); - // Thread.dumpStack(); - } - hmon = _hmon; - return true; - } - } - return false; - } - - protected void createNativeImpl() { - final WindowsScreen screen = (WindowsScreen) getScreen(); - final WindowsDisplay display = (WindowsDisplay) screen.getDisplay(); - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - setGraphicsConfiguration(cfg); - final int flags = getReconfigureFlags(0, true) & - ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; - setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(), - getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); - if (getWindowHandle() == 0) { - throw new NativeWindowException("Error creating window"); - } - windowHandleClose = getWindowHandle(); - addMouseListener(new MouseTracker()); - - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+ - " (Parent HWND "+toHexString(getParentWindowHandle())+ - ") : HWND "+toHexString(getWindowHandle())+", "+Thread.currentThread()); - e.printStackTrace(); - } - } - - class MouseTracker extends MouseAdapter { - public void mouseEntered(MouseEvent e) { - WindowsWindow.trackPointerLeave0(WindowsWindow.this.getWindowHandle()); - } - } - - protected void closeNativeImpl() { - if(windowHandleClose != 0) { - if (hdc != 0) { - try { - GDI.ReleaseDC(windowHandleClose, hdc); - } catch (Throwable t) { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); - e.printStackTrace(); - } - } - } - try { - GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent - GDI.DestroyWindow(windowHandleClose); - } catch (Throwable t) { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); - e.printStackTrace(); - } - } finally { - windowHandleClose = 0; - } - } - hdc = 0; - hdc_old = 0; - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("WindowsWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ - getReconfigureFlagsAsString(null, flags)); - } - - if(0 == ( FLAG_IS_UNDECORATED & flags)) { - final InsetsImmutable i = getInsets(); - - // client position -> top-level window position - x -= i.getLeftWidth() ; - y -= i.getTopHeight() ; - - if(0 top-level window size - width += i.getTotalWidth(); - height += i.getTotalHeight(); - } - } - reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags); - - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); - } - return true; - } - - protected void requestFocusImpl(boolean force) { - requestFocus0(getWindowHandle(), force); - } - - @Override - protected void setTitleImpl(final String title) { - setTitle0(getWindowHandle(), title); - } - - @Override - protected boolean setPointerVisibleImpl(final boolean pointerVisible) { - final Boolean[] res = new Boolean[] { Boolean.FALSE }; - - this.runOnEDTIfAvail(true, new Runnable() { - public void run() { - res[0] = Boolean.valueOf(setPointerVisible0(getWindowHandle(), pointerVisible)); - } - }); - return res[0].booleanValue(); - } - - @Override - protected boolean confinePointerImpl(final boolean confine) { - final Boolean[] res = new Boolean[] { Boolean.FALSE }; - - this.runOnEDTIfAvail(true, new Runnable() { - public void run() { - final Point p0 = getLocationOnScreenImpl(0, 0); - res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine, - p0.getX(), p0.getY(), p0.getX()+getWidth(), p0.getY()+getHeight())); - } - }); - return res[0].booleanValue(); - } - - @Override - protected void warpPointerImpl(final int x, final int y) { - this.runOnEDTIfAvail(true, new Runnable() { - public void run() { - final Point sPos = getLocationOnScreenImpl(x, y); - warpPointer0(getWindowHandle(), sPos.getX(), sPos.getY()); - } - }); - return; - } - - protected Point getLocationOnScreenImpl(int x, int y) { - return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop - using event driven insetsChange(..) - } - - private final int validateKeyCode(int eventType, int keyCode) { - switch(eventType) { - case KeyEvent.EVENT_KEY_PRESSED: - lastPressedKeyCode = keyCode; - break; - case KeyEvent.EVENT_KEY_TYPED: - if(-1==keyCode) { - keyCode = lastPressedKeyCode; - } - lastPressedKeyCode = -1; - break; - } - return keyCode; - } - private int lastPressedKeyCode = 0; - - @Override - public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform - keyCode = validateKeyCode(eventType, keyCode); - super.sendKeyEvent(eventType, modifiers, keyCode, keyChar); - } - - @Override - public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { - // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform - keyCode = validateKeyCode(eventType, keyCode); - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar); - } - - //---------------------------------------------------------------------- - // Internals only - // - protected static native boolean initIDs0(); - protected static native long getNewtWndProc0(); - - private native long CreateWindow0(long hInstance, String wndClassName, String wndName, - long parentWindowHandle, - int x, int y, int width, int height, boolean autoPosition, int flags); - private native long MonitorFromWindow0(long windowHandle); - private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, - int x, int y, int width, int height, int flags); - private static native void setTitle0(long windowHandle, String title); - private native void requestFocus0(long windowHandle, boolean force); - - private static native boolean setPointerVisible0(long windowHandle, boolean visible); - private static native boolean confinePointer0(long windowHandle, boolean grab, int l, int t, int r, int b); - private static native void warpPointer0(long windowHandle, int x, int y); - private static native void trackPointerLeave0(long windowHandle); -} diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java new file mode 100644 index 000000000..714324d63 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.x11; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowFactory; + +import com.jogamp.nativewindow.x11.X11GraphicsDevice; + +import jogamp.nativewindow.x11.X11Util; +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; + +public class DisplayDriver extends DisplayImpl { + + static { + NEWTJNILibLoader.loadNEWT(); + + if ( !initIDs0(X11Util.XERROR_STACKDUMP) ) { + throw new NativeWindowException("Failed to initialize X11Display jmethodIDs"); + } + + if (!WindowDriver.initIDs0()) { + throw new NativeWindowException("Failed to initialize X11Window jmethodIDs"); + } + } + + public static void initSingleton() { + // just exist to ensure static init has been run + } + + + public DisplayDriver() { + } + + public String validateDisplayName(String name, long handle) { + return X11Util.validateDisplayName(name, handle); + } + + /** + * {@inheritDoc} + * + * We use a private non-shared X11 Display instance for EDT window operations and one for exposed animation, eg. OpenGL. + *

+ * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED}, + * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms. + *

+ *

+ * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)}, + * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}. + *

+ */ + @SuppressWarnings("unused") + protected void createNativeImpl() { + long handle = X11Util.openDisplay(name); + if( 0 == handle ) { + throw new RuntimeException("Error creating display(Win): "+name); + } + if(USE_SEPARATE_DISPLAY_FOR_EDT) { + edtDisplayHandle = X11Util.openDisplay(name); + if( 0 == edtDisplayHandle ) { + X11Util.closeDisplay(handle); + throw new RuntimeException("Error creating display(EDT): "+name); + } + } else { + edtDisplayHandle = handle; + } + try { + CompleteDisplay0(edtDisplayHandle); + } catch(RuntimeException e) { + closeNativeImpl(); + throw e; + } + + // see API doc above! + if(X11Util.XINITTHREADS_ALWAYS_ENABLED && X11Util.HAS_XLOCKDISPLAY_BUG) { + aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), false); + } else { + aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, false); + } + } + + protected void closeNativeImpl() { + DisplayRelease0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom); + javaObjectAtom = 0; + windowDeleteAtom = 0; + // closing using ATI driver bug 'same order' + final long handle = getHandle(); + X11Util.closeDisplay(handle); + if(handle != edtDisplayHandle) { + X11Util.closeDisplay(edtDisplayHandle); + } + edtDisplayHandle = 0; + } + + protected void dispatchMessagesNative() { + if(0 != edtDisplayHandle) { + DispatchMessages0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom); + } + } + + protected long getEDTHandle() { return edtDisplayHandle; } + protected long getJavaObjectAtom() { return javaObjectAtom; } + protected long getWindowDeleteAtom() { return windowDeleteAtom; } + + //---------------------------------------------------------------------- + // Internals only + // + private static native boolean initIDs0(boolean debug); + + private native void CompleteDisplay0(long handle); + + private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) { + this.javaObjectAtom=javaObjectAtom; + this.windowDeleteAtom=windowDeleteAtom; + } + private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom); + + private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom); + + /** + * 2011/06/14 libX11 1.4.2 and libxcb 1.7 bug 20708 - Multithreading Issues w/ OpenGL, .. + * https://bugs.freedesktop.org/show_bug.cgi?id=20708 + * https://jogamp.org/bugzilla/show_bug.cgi?id=502 + * Affects: Ubuntu 11.04, OpenSuSE 11, .. + * Workaround: Using a separate X11 Display connection for event dispatching (EDT) + */ + private final boolean USE_SEPARATE_DISPLAY_FOR_EDT = true; + + private long edtDisplayHandle; + + /** X11 Window delete atom marker used on EDT */ + private long windowDeleteAtom; + + /** X11 Window java object property used on EDT */ + private long javaObjectAtom; +} + diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java new file mode 100644 index 000000000..10f6b84da --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ +package jogamp.newt.driver.x11; + +import java.util.List; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + +import jogamp.nativewindow.x11.X11Util; +import jogamp.newt.DisplayImpl; +import jogamp.newt.DisplayImpl.DisplayRunnable; +import jogamp.newt.ScreenImpl; + +import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; + +public class ScreenDriver extends ScreenImpl { + + static { + DisplayDriver.initSingleton(); + } + + public ScreenDriver() { + } + + protected void createNativeImpl() { + // validate screen index + Long handle = display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Long run(long dpy) { + return new Long(GetScreen0(dpy, screen_idx)); + } } ); + if (handle.longValue() == 0) { + throw new RuntimeException("Error creating screen: " + screen_idx); + } + aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx); + } + + protected void closeNativeImpl() { + } + + private int[] nrotations; + private int nrotation_index; + private int nres_number; + private int nres_index; + private int[] nrates; + private int nrate_index; + private int nmode_number; + + protected int[] getScreenModeFirstImpl() { + return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public int[] run(long dpy) { + // initialize iterators and static data + nrotations = getAvailableScreenModeRotations0(dpy, screen_idx); + if(null==nrotations || 0==nrotations.length) { + return null; + } + nrotation_index = 0; + + nres_number = getNumScreenModeResolutions0(dpy, screen_idx); + if(0==nres_number) { + return null; + } + nres_index = 0; + + nrates = getScreenModeRates0(dpy, screen_idx, nres_index); + if(null==nrates || 0==nrates.length) { + return null; + } + nrate_index = 0; + + nmode_number = 0; + + return getScreenModeNextImpl(); + } } ); + } + + protected int[] getScreenModeNextImpl() { + // assemble: w x h x bpp x f x r + return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public int[] run(long dpy) { + /** + System.err.println("******** mode: "+nmode_number); + System.err.println("rot "+nrotation_index); + System.err.println("rate "+nrate_index); + System.err.println("res "+nres_index); */ + + int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index); + if(null==res || 0==res.length) { + return null; + } + if(0>=res[0] || 0>=res[1]) { + throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number); + } + int rate = nrates[nrate_index]; + if(0>=rate) { + rate = default_sm_rate; + if(DEBUG) { + System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+default_sm_rate); + } + } + int rotation = nrotations[nrotation_index]; + + int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ]; + int i = 0; + props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode + props[i++] = 0; // set later for verification of iterator + props[i++] = res[0]; // width + props[i++] = res[1]; // height + props[i++] = default_sm_bpp; // FIXME + props[i++] = res[2]; // widthmm + props[i++] = res[3]; // heightmm + props[i++] = rate; // rate + props[i++] = rotation; + props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element + + nmode_number++; + + // iteration: r -> f -> bpp -> [w x h] + nrotation_index++; + if(nrotation_index == nrotations.length) { + nrotation_index=0; + nrate_index++; + if(null == nrates || nrate_index == nrates.length){ + nres_index++; + if(nres_index == nres_number) { + // done + nrates=null; + nrotations=null; + return null; + } + + nrates = getScreenModeRates0(dpy, screen_idx, nres_index); + if(null==nrates || 0==nrates.length) { + return null; + } + nrate_index = 0; + } + } + + return props; + } } ); + } + + protected ScreenMode getCurrentScreenModeImpl() { + return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public ScreenMode run(long dpy) { + long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); + if(0 == screenConfigHandle) { + return null; + } + int[] res; + int rate, rot; + try { + int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); + if(0==resNumber) { + return null; + } + + int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle); + if(0>resIdx) { + return null; + } + if(resIdx>=resNumber) { + throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber); + } + res = getScreenModeResolution0(dpy, screen_idx, resIdx); + if(null==res || 0==res.length) { + return null; + } + if(0>=res[0] || 0>=res[1]) { + throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber); + } + rate = getCurrentScreenRate0(screenConfigHandle); + if(0>rate) { + return null; + } + rot = getCurrentScreenRotation0(screenConfigHandle); + if(0>rot) { + return null; + } + } finally { + freeScreenConfiguration0(screenConfigHandle); + } + int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; + int i = 0; + props[i++] = 0; // set later for verification of iterator + props[i++] = res[0]; // width + props[i++] = res[1]; // height + props[i++] = default_sm_bpp; // FIXME + props[i++] = res[2]; // widthmm + props[i++] = res[3]; // heightmm + props[i++] = rate; // rate + props[i++] = rot; + props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count + return ScreenModeUtil.streamIn(props, 0); + } } ); + } + + protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { + final List screenModes = this.getScreenModesOrig(); + final int screenModeIdx = screenModes.indexOf(screenMode); + if(0>screenModeIdx) { + throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); + } + final long t0 = System.currentTimeMillis(); + boolean done = runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Boolean run(long dpy) { + boolean done = false; + long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); + if(0 == screenConfigHandle) { + return Boolean.valueOf(done); + } + try { + int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); + int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); + if(0>resIdx || resIdx>=resNumber) { + throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode); + } + + final int f = screenMode.getMonitorMode().getRefreshRate(); + final int r = screenMode.getRotation(); + + if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resIdx, f, r) ) { + while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) { + done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r); + if(!done) { + try { Thread.sleep(10); } catch (InterruptedException e) { } + } + } + } + } finally { + freeScreenConfiguration0(screenConfigHandle); + } + return Boolean.valueOf(done); + } + }).booleanValue(); + + if(DEBUG || !done) { + System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ + (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode); + } + return done; + } + + private class XineramaEnabledQuery implements DisplayImpl.DisplayRunnable { + public Boolean run(long dpy) { + return new Boolean(X11Util.XineramaIsEnabled(dpy)); + } + } + private XineramaEnabledQuery xineramaEnabledQuery = new XineramaEnabledQuery(); + + protected int validateScreenIndex(final int idx) { + if(getDisplay().isNativeValid()) { + return runWithLockedDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; + } else { + return runWithTempDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; + } + } + + protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) { + display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(getWidth0(dpy, screen_idx)); + virtualSize.setHeight(getHeight0(dpy, screen_idx)); + return null; + } } ); + } + + //---------------------------------------------------------------------- + // Internals only + // + private final T runWithLockedDisplayHandle(DisplayRunnable action) { + return display.runWithLockedDisplayHandle(action); + // return runWithTempDisplayHandle(action); + // return runWithoutLock(action); + } + + private final T runWithTempDisplayHandle(DisplayRunnable action) { + final long displayHandle = X11Util.openDisplay(display.getName()); + if(0 == displayHandle) { + throw new RuntimeException("null device"); + } + T res; + try { + res = action.run(displayHandle); + } finally { + X11Util.closeDisplay(displayHandle); + } + return res; + } + private final T runWithoutLock(DisplayRunnable action) { + return action.run(display.getHandle()); + } + + private static native long GetScreen0(long dpy, int scrn_idx); + + private static native int getWidth0(long display, int scrn_idx); + + private static native int getHeight0(long display, int scrn_idx); + + /** @return int[] { rot1, .. } */ + private static native int[] getAvailableScreenModeRotations0(long display, int screen_index); + + private static native int getNumScreenModeResolutions0(long display, int screen_index); + + /** @return int[] { width, height, widthmm, heightmm } */ + private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index); + + private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index); + + private static native long getScreenConfiguration0(long display, int screen_index); + private static native void freeScreenConfiguration0(long screenConfiguration); + + private static native int getCurrentScreenResolutionIndex0(long screenConfiguration); + private static native int getCurrentScreenRate0(long screenConfiguration); + private static native int getCurrentScreenRotation0(long screenConfiguration); + + /** needs own Display connection for XRANDR event handling */ + private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot); + private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot); +} diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java new file mode 100644 index 000000000..97d1ae3db --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package jogamp.newt.driver.x11; + +import jogamp.nativewindow.x11.X11Lib; +import jogamp.newt.DisplayImpl; +import jogamp.newt.DisplayImpl.DisplayRunnable; +import jogamp.newt.WindowImpl; +import javax.media.nativewindow.*; +import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.Point; + +import com.jogamp.newt.event.MouseEvent; + +public class WindowDriver extends WindowImpl { + private static final String WINDOW_CLASS_NAME = "NewtWindow"; + private static final int X11_WHEEL_ONE_UP_BUTTON = 4; + private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5; + private static final int X11_WHEEL_TWO_UP_BUTTON = 6; + private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7; + + static { + DisplayDriver.initSingleton(); + } + + public WindowDriver() { + } + + protected void createNativeImpl() { + final ScreenDriver screen = (ScreenDriver) getScreen(); + final DisplayDriver display = (DisplayDriver) screen.getDisplay(); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested); + final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if(DEBUG_IMPLEMENTATION) { + System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg); + } + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + final int visualID = cfg.getVisualID(VIDType.NATIVE); + if(VisualIDHolder.VID_UNDEFINED == visualID) { + throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg); + } + setGraphicsConfiguration(cfg); + final int flags = getReconfigureFlags(0, true) & + ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; + setWindowHandle(CreateWindow0(getParentWindowHandle(), + display.getEDTHandle(), screen.getIndex(), visualID, + display.getJavaObjectAtom(), display.getWindowDeleteAtom(), + getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); + windowHandleClose = getWindowHandle(); + if (0 == windowHandleClose) { + throw new NativeWindowException("Error creating window"); + } + } + + protected void closeNativeImpl() { + if(0!=windowHandleClose && null!=getScreen() ) { + DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); + try { + CloseWindow0(display.getEDTHandle(), windowHandleClose, + display.getJavaObjectAtom(), display.getWindowDeleteAtom()); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + } + } + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ + getReconfigureFlagsAsString(null, flags)); + } + if(0 == ( FLAG_IS_UNDECORATED & flags)) { + final InsetsImmutable i = getInsets(); + + // client position -> top-level window position + x -= i.getLeftWidth() ; + y -= i.getTopHeight() ; + } + final DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); + reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(), + getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(), + x, y, width, height, flags); + + return true; + } + + protected void reparentNotify(long newParentWindowHandle) { + if(DEBUG_IMPLEMENTATION) { + final long p0 = getParentWindowHandle(); + System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle)); + } + } + + protected void requestFocusImpl(boolean force) { + requestFocus0(getDisplayEDTHandle(), getWindowHandle(), force); + } + + @Override + protected void setTitleImpl(final String title) { + runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + setTitle0(dpy, getWindowHandle(), title); + return null; + } + }); + } + + @Override + protected boolean setPointerVisibleImpl(final boolean pointerVisible) { + return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Boolean run(long dpy) { + return Boolean.valueOf(setPointerVisible0(getDisplayEDTHandle(), getWindowHandle(), pointerVisible)); + } + }).booleanValue(); + } + + @Override + protected boolean confinePointerImpl(final boolean confine) { + return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Boolean run(long dpy) { + return Boolean.valueOf(confinePointer0(getDisplayEDTHandle(), getWindowHandle(), confine)); + } + }).booleanValue(); + } + + @Override + protected void warpPointerImpl(final int x, final int y) { + runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + warpPointer0(getDisplayEDTHandle(), getWindowHandle(), x, y); + return null; + } + }); + } + + protected Point getLocationOnScreenImpl(final int x, final int y) { + // X11Util.GetRelativeLocation: locks display already ! + return X11Lib.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); + } + + protected void updateInsetsImpl(Insets insets) { + // nop - using event driven insetsChange(..) + } + + protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, + int x, int y, int button, int rotation) { + switch(eventType) { + case MouseEvent.EVENT_MOUSE_PRESSED: + switch(button) { + case X11_WHEEL_ONE_UP_BUTTON: + case X11_WHEEL_ONE_DOWN_BUTTON: + case X11_WHEEL_TWO_UP_BUTTON: + case X11_WHEEL_TWO_DOWN_BUTTON: + // ignore wheel pressed ! + return; + } + break; + case MouseEvent.EVENT_MOUSE_RELEASED: + switch(button) { + case X11_WHEEL_ONE_UP_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 1; + rotation = 1; + break; + case X11_WHEEL_ONE_DOWN_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 1; + rotation = -1; + break; + case X11_WHEEL_TWO_UP_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 2; + rotation = 1; + break; + case X11_WHEEL_TWO_DOWN_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 2; + rotation = -1; + break; + } + break; + } + super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation); + } + + + //---------------------------------------------------------------------- + // Internals only + // + + private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI + private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI + + private final long getDisplayEDTHandle() { + return ((DisplayDriver) getScreen().getDisplay()).getEDTHandle(); + } + private final T runWithLockedDisplayHandle(DisplayRunnable action) { + return ((DisplayImpl) getScreen().getDisplay()).runWithLockedDisplayHandle(action); + // return runWithTempDisplayHandle(action); + } + + protected static native boolean initIDs0(); + + private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, + int visualID, long javaObjectAtom, long windowDeleteAtom, + int x, int y, int width, int height, boolean autoPosition, int flags); + private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); + private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, + long windowDeleteAtom, int x, int y, int width, int height, int flags); + private native void requestFocus0(long display, long windowHandle, boolean force); + + private static native void setTitle0(long display, long windowHandle, String title); + private static native long getParentWindow0(long display, long windowHandle); + private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible); + private static native boolean confinePointer0(long display, long windowHandle, boolean grab); + private static native void warpPointer0(long display, long windowHandle, int x, int y); + + private long windowHandleClose; +} diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java b/src/newt/classes/jogamp/newt/driver/x11/X11Display.java deleted file mode 100644 index 8243fcf9d..000000000 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.x11; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.NativeWindowFactory; - -import com.jogamp.nativewindow.x11.X11GraphicsDevice; - -import jogamp.nativewindow.x11.X11Util; -import jogamp.newt.DisplayImpl; -import jogamp.newt.NEWTJNILibLoader; - -public class X11Display extends DisplayImpl { - - static { - NEWTJNILibLoader.loadNEWT(); - - if ( !initIDs0(X11Util.XERROR_STACKDUMP) ) { - throw new NativeWindowException("Failed to initialize X11Display jmethodIDs"); - } - - if (!X11Window.initIDs0()) { - throw new NativeWindowException("Failed to initialize X11Window jmethodIDs"); - } - } - - public static void initSingleton() { - // just exist to ensure static init has been run - } - - - public X11Display() { - } - - public String validateDisplayName(String name, long handle) { - return X11Util.validateDisplayName(name, handle); - } - - /** - * {@inheritDoc} - * - * We use a private non-shared X11 Display instance for EDT window operations and one for exposed animation, eg. OpenGL. - *

- * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED}, - * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms. - *

- *

- * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)}, - * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}. - *

- */ - @SuppressWarnings("unused") - protected void createNativeImpl() { - long handle = X11Util.openDisplay(name); - if( 0 == handle ) { - throw new RuntimeException("Error creating display(Win): "+name); - } - if(USE_SEPARATE_DISPLAY_FOR_EDT) { - edtDisplayHandle = X11Util.openDisplay(name); - if( 0 == edtDisplayHandle ) { - X11Util.closeDisplay(handle); - throw new RuntimeException("Error creating display(EDT): "+name); - } - } else { - edtDisplayHandle = handle; - } - try { - CompleteDisplay0(edtDisplayHandle); - } catch(RuntimeException e) { - closeNativeImpl(); - throw e; - } - - // see API doc above! - if(X11Util.XINITTHREADS_ALWAYS_ENABLED && X11Util.HAS_XLOCKDISPLAY_BUG) { - aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), false); - } else { - aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, false); - } - } - - protected void closeNativeImpl() { - DisplayRelease0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom); - javaObjectAtom = 0; - windowDeleteAtom = 0; - // closing using ATI driver bug 'same order' - final long handle = getHandle(); - X11Util.closeDisplay(handle); - if(handle != edtDisplayHandle) { - X11Util.closeDisplay(edtDisplayHandle); - } - edtDisplayHandle = 0; - } - - protected void dispatchMessagesNative() { - if(0 != edtDisplayHandle) { - DispatchMessages0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom); - } - } - - protected long getEDTHandle() { return edtDisplayHandle; } - protected long getJavaObjectAtom() { return javaObjectAtom; } - protected long getWindowDeleteAtom() { return windowDeleteAtom; } - - //---------------------------------------------------------------------- - // Internals only - // - private static native boolean initIDs0(boolean debug); - - private native void CompleteDisplay0(long handle); - - private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) { - this.javaObjectAtom=javaObjectAtom; - this.windowDeleteAtom=windowDeleteAtom; - } - private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom); - - private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom); - - /** - * 2011/06/14 libX11 1.4.2 and libxcb 1.7 bug 20708 - Multithreading Issues w/ OpenGL, .. - * https://bugs.freedesktop.org/show_bug.cgi?id=20708 - * https://jogamp.org/bugzilla/show_bug.cgi?id=502 - * Affects: Ubuntu 11.04, OpenSuSE 11, .. - * Workaround: Using a separate X11 Display connection for event dispatching (EDT) - */ - private final boolean USE_SEPARATE_DISPLAY_FOR_EDT = true; - - private long edtDisplayHandle; - - /** X11 Window delete atom marker used on EDT */ - private long windowDeleteAtom; - - /** X11 Window java object property used on EDT */ - private long javaObjectAtom; -} - diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java deleted file mode 100644 index 93db854ac..000000000 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ -package jogamp.newt.driver.x11; - -import java.util.List; - -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; - -import jogamp.nativewindow.x11.X11Util; -import jogamp.newt.DisplayImpl; -import jogamp.newt.DisplayImpl.DisplayRunnable; -import jogamp.newt.ScreenImpl; - -import com.jogamp.nativewindow.x11.X11GraphicsDevice; -import com.jogamp.nativewindow.x11.X11GraphicsScreen; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; - -public class X11Screen extends ScreenImpl { - - static { - X11Display.initSingleton(); - } - - public X11Screen() { - } - - protected void createNativeImpl() { - // validate screen index - Long handle = display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Long run(long dpy) { - return new Long(GetScreen0(dpy, screen_idx)); - } } ); - if (handle.longValue() == 0) { - throw new RuntimeException("Error creating screen: " + screen_idx); - } - aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx); - } - - protected void closeNativeImpl() { - } - - private int[] nrotations; - private int nrotation_index; - private int nres_number; - private int nres_index; - private int[] nrates; - private int nrate_index; - private int nmode_number; - - protected int[] getScreenModeFirstImpl() { - return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public int[] run(long dpy) { - // initialize iterators and static data - nrotations = getAvailableScreenModeRotations0(dpy, screen_idx); - if(null==nrotations || 0==nrotations.length) { - return null; - } - nrotation_index = 0; - - nres_number = getNumScreenModeResolutions0(dpy, screen_idx); - if(0==nres_number) { - return null; - } - nres_index = 0; - - nrates = getScreenModeRates0(dpy, screen_idx, nres_index); - if(null==nrates || 0==nrates.length) { - return null; - } - nrate_index = 0; - - nmode_number = 0; - - return getScreenModeNextImpl(); - } } ); - } - - protected int[] getScreenModeNextImpl() { - // assemble: w x h x bpp x f x r - return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public int[] run(long dpy) { - /** - System.err.println("******** mode: "+nmode_number); - System.err.println("rot "+nrotation_index); - System.err.println("rate "+nrate_index); - System.err.println("res "+nres_index); */ - - int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index); - if(null==res || 0==res.length) { - return null; - } - if(0>=res[0] || 0>=res[1]) { - throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number); - } - int rate = nrates[nrate_index]; - if(0>=rate) { - rate = default_sm_rate; - if(DEBUG) { - System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+default_sm_rate); - } - } - int rotation = nrotations[nrotation_index]; - - int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ]; - int i = 0; - props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode - props[i++] = 0; // set later for verification of iterator - props[i++] = res[0]; // width - props[i++] = res[1]; // height - props[i++] = default_sm_bpp; // FIXME - props[i++] = res[2]; // widthmm - props[i++] = res[3]; // heightmm - props[i++] = rate; // rate - props[i++] = rotation; - props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element - - nmode_number++; - - // iteration: r -> f -> bpp -> [w x h] - nrotation_index++; - if(nrotation_index == nrotations.length) { - nrotation_index=0; - nrate_index++; - if(null == nrates || nrate_index == nrates.length){ - nres_index++; - if(nres_index == nres_number) { - // done - nrates=null; - nrotations=null; - return null; - } - - nrates = getScreenModeRates0(dpy, screen_idx, nres_index); - if(null==nrates || 0==nrates.length) { - return null; - } - nrate_index = 0; - } - } - - return props; - } } ); - } - - protected ScreenMode getCurrentScreenModeImpl() { - return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public ScreenMode run(long dpy) { - long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); - if(0 == screenConfigHandle) { - return null; - } - int[] res; - int rate, rot; - try { - int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); - if(0==resNumber) { - return null; - } - - int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle); - if(0>resIdx) { - return null; - } - if(resIdx>=resNumber) { - throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber); - } - res = getScreenModeResolution0(dpy, screen_idx, resIdx); - if(null==res || 0==res.length) { - return null; - } - if(0>=res[0] || 0>=res[1]) { - throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber); - } - rate = getCurrentScreenRate0(screenConfigHandle); - if(0>rate) { - return null; - } - rot = getCurrentScreenRotation0(screenConfigHandle); - if(0>rot) { - return null; - } - } finally { - freeScreenConfiguration0(screenConfigHandle); - } - int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; - int i = 0; - props[i++] = 0; // set later for verification of iterator - props[i++] = res[0]; // width - props[i++] = res[1]; // height - props[i++] = default_sm_bpp; // FIXME - props[i++] = res[2]; // widthmm - props[i++] = res[3]; // heightmm - props[i++] = rate; // rate - props[i++] = rot; - props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count - return ScreenModeUtil.streamIn(props, 0); - } } ); - } - - protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { - final List screenModes = this.getScreenModesOrig(); - final int screenModeIdx = screenModes.indexOf(screenMode); - if(0>screenModeIdx) { - throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); - } - final long t0 = System.currentTimeMillis(); - boolean done = runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Boolean run(long dpy) { - boolean done = false; - long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); - if(0 == screenConfigHandle) { - return Boolean.valueOf(done); - } - try { - int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); - int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); - if(0>resIdx || resIdx>=resNumber) { - throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode); - } - - final int f = screenMode.getMonitorMode().getRefreshRate(); - final int r = screenMode.getRotation(); - - if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resIdx, f, r) ) { - while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) { - done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r); - if(!done) { - try { Thread.sleep(10); } catch (InterruptedException e) { } - } - } - } - } finally { - freeScreenConfiguration0(screenConfigHandle); - } - return Boolean.valueOf(done); - } - }).booleanValue(); - - if(DEBUG || !done) { - System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ - (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode); - } - return done; - } - - private class XineramaEnabledQuery implements DisplayImpl.DisplayRunnable { - public Boolean run(long dpy) { - return new Boolean(X11Util.XineramaIsEnabled(dpy)); - } - } - private XineramaEnabledQuery xineramaEnabledQuery = new XineramaEnabledQuery(); - - protected int validateScreenIndex(final int idx) { - if(getDisplay().isNativeValid()) { - return runWithLockedDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; - } else { - return runWithTempDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; - } - } - - protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) { - display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Object run(long dpy) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(getWidth0(dpy, screen_idx)); - virtualSize.setHeight(getHeight0(dpy, screen_idx)); - return null; - } } ); - } - - //---------------------------------------------------------------------- - // Internals only - // - private final T runWithLockedDisplayHandle(DisplayRunnable action) { - return display.runWithLockedDisplayHandle(action); - // return runWithTempDisplayHandle(action); - // return runWithoutLock(action); - } - - private final T runWithTempDisplayHandle(DisplayRunnable action) { - final long displayHandle = X11Util.openDisplay(display.getName()); - if(0 == displayHandle) { - throw new RuntimeException("null device"); - } - T res; - try { - res = action.run(displayHandle); - } finally { - X11Util.closeDisplay(displayHandle); - } - return res; - } - private final T runWithoutLock(DisplayRunnable action) { - return action.run(display.getHandle()); - } - - private static native long GetScreen0(long dpy, int scrn_idx); - - private static native int getWidth0(long display, int scrn_idx); - - private static native int getHeight0(long display, int scrn_idx); - - /** @return int[] { rot1, .. } */ - private static native int[] getAvailableScreenModeRotations0(long display, int screen_index); - - private static native int getNumScreenModeResolutions0(long display, int screen_index); - - /** @return int[] { width, height, widthmm, heightmm } */ - private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index); - - private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index); - - private static native long getScreenConfiguration0(long display, int screen_index); - private static native void freeScreenConfiguration0(long screenConfiguration); - - private static native int getCurrentScreenResolutionIndex0(long screenConfiguration); - private static native int getCurrentScreenRate0(long screenConfiguration); - private static native int getCurrentScreenRotation0(long screenConfiguration); - - /** needs own Display connection for XRANDR event handling */ - private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot); - private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot); -} diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java deleted file mode 100644 index 5501f5a3c..000000000 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package jogamp.newt.driver.x11; - -import jogamp.nativewindow.x11.X11Lib; -import jogamp.newt.DisplayImpl; -import jogamp.newt.DisplayImpl.DisplayRunnable; -import jogamp.newt.WindowImpl; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.nativewindow.util.Insets; -import javax.media.nativewindow.util.InsetsImmutable; -import javax.media.nativewindow.util.Point; - -import com.jogamp.newt.event.MouseEvent; - -public class X11Window extends WindowImpl { - private static final String WINDOW_CLASS_NAME = "NewtWindow"; - private static final int X11_WHEEL_ONE_UP_BUTTON = 4; - private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5; - private static final int X11_WHEEL_TWO_UP_BUTTON = 6; - private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7; - - static { - X11Display.initSingleton(); - } - - public X11Window() { - } - - protected void createNativeImpl() { - final X11Screen screen = (X11Screen) getScreen(); - final X11Display display = (X11Display) screen.getDisplay(); - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested); - final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg); - } - if (null == cfg) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } - final int visualID = cfg.getVisualID(VIDType.NATIVE); - if(VisualIDHolder.VID_UNDEFINED == visualID) { - throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg); - } - setGraphicsConfiguration(cfg); - final int flags = getReconfigureFlags(0, true) & - ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; - setWindowHandle(CreateWindow0(getParentWindowHandle(), - display.getEDTHandle(), screen.getIndex(), visualID, - display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); - windowHandleClose = getWindowHandle(); - if (0 == windowHandleClose) { - throw new NativeWindowException("Error creating window"); - } - } - - protected void closeNativeImpl() { - if(0!=windowHandleClose && null!=getScreen() ) { - X11Display display = (X11Display) getScreen().getDisplay(); - try { - CloseWindow0(display.getEDTHandle(), windowHandleClose, - display.getJavaObjectAtom(), display.getWindowDeleteAtom()); - } catch (Throwable t) { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); - e.printStackTrace(); - } - } finally { - windowHandleClose = 0; - } - } - } - - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ - getReconfigureFlagsAsString(null, flags)); - } - if(0 == ( FLAG_IS_UNDECORATED & flags)) { - final InsetsImmutable i = getInsets(); - - // client position -> top-level window position - x -= i.getLeftWidth() ; - y -= i.getTopHeight() ; - } - final X11Display display = (X11Display) getScreen().getDisplay(); - reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(), - getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(), - x, y, width, height, flags); - - return true; - } - - protected void reparentNotify(long newParentWindowHandle) { - if(DEBUG_IMPLEMENTATION) { - final long p0 = getParentWindowHandle(); - System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle)); - } - } - - protected void requestFocusImpl(boolean force) { - requestFocus0(getDisplayEDTHandle(), getWindowHandle(), force); - } - - @Override - protected void setTitleImpl(final String title) { - runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Object run(long dpy) { - setTitle0(dpy, getWindowHandle(), title); - return null; - } - }); - } - - @Override - protected boolean setPointerVisibleImpl(final boolean pointerVisible) { - return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Boolean run(long dpy) { - return Boolean.valueOf(setPointerVisible0(getDisplayEDTHandle(), getWindowHandle(), pointerVisible)); - } - }).booleanValue(); - } - - @Override - protected boolean confinePointerImpl(final boolean confine) { - return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Boolean run(long dpy) { - return Boolean.valueOf(confinePointer0(getDisplayEDTHandle(), getWindowHandle(), confine)); - } - }).booleanValue(); - } - - @Override - protected void warpPointerImpl(final int x, final int y) { - runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { - public Object run(long dpy) { - warpPointer0(getDisplayEDTHandle(), getWindowHandle(), x, y); - return null; - } - }); - } - - protected Point getLocationOnScreenImpl(final int x, final int y) { - // X11Util.GetRelativeLocation: locks display already ! - return X11Lib.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); - } - - protected void updateInsetsImpl(Insets insets) { - // nop - using event driven insetsChange(..) - } - - protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, - int x, int y, int button, int rotation) { - switch(eventType) { - case MouseEvent.EVENT_MOUSE_PRESSED: - switch(button) { - case X11_WHEEL_ONE_UP_BUTTON: - case X11_WHEEL_ONE_DOWN_BUTTON: - case X11_WHEEL_TWO_UP_BUTTON: - case X11_WHEEL_TWO_DOWN_BUTTON: - // ignore wheel pressed ! - return; - } - break; - case MouseEvent.EVENT_MOUSE_RELEASED: - switch(button) { - case X11_WHEEL_ONE_UP_BUTTON: - eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; - button = 1; - rotation = 1; - break; - case X11_WHEEL_ONE_DOWN_BUTTON: - eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; - button = 1; - rotation = -1; - break; - case X11_WHEEL_TWO_UP_BUTTON: - eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; - button = 2; - rotation = 1; - break; - case X11_WHEEL_TWO_DOWN_BUTTON: - eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; - button = 2; - rotation = -1; - break; - } - break; - } - super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation); - } - - - //---------------------------------------------------------------------- - // Internals only - // - - private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI - private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI - - private final long getDisplayEDTHandle() { - return ((X11Display) getScreen().getDisplay()).getEDTHandle(); - } - private final T runWithLockedDisplayHandle(DisplayRunnable action) { - return ((DisplayImpl) getScreen().getDisplay()).runWithLockedDisplayHandle(action); - // return runWithTempDisplayHandle(action); - } - - protected static native boolean initIDs0(); - - private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, - int visualID, long javaObjectAtom, long windowDeleteAtom, - int x, int y, int width, int height, boolean autoPosition, int flags); - private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); - private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, - long windowDeleteAtom, int x, int y, int width, int height, int flags); - private native void requestFocus0(long display, long windowHandle, boolean force); - - private static native void setTitle0(long display, long windowHandle, String title); - private static native long getParentWindow0(long display, long windowHandle); - private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible); - private static native boolean confinePointer0(long display, long windowHandle, boolean grab); - private static native void warpPointer0(long display, long windowHandle, int x, int y); - - private long windowHandleClose; -} diff --git a/src/newt/native/AndroidWindow.c b/src/newt/native/AndroidWindow.c index fa5765672..94695e1d3 100644 --- a/src/newt/native/AndroidWindow.c +++ b/src/newt/native/AndroidWindow.c @@ -9,7 +9,7 @@ #include #include -#include "jogamp_newt_driver_android_AndroidWindow.h" +#include "jogamp_newt_driver_android_WindowDriver.h" #include #include @@ -23,56 +23,56 @@ #endif -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getSurfaceHandle0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_android_WindowDriver_getSurfaceHandle0 (JNIEnv *env, jclass clazz, jobject surface) { ANativeWindow * anw = ANativeWindow_fromSurface(env, surface); return (jlong) (intptr_t) anw; } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getSurfaceVisualID0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getSurfaceVisualID0 (JNIEnv *env, jclass clazz, jlong surfaceHandle) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; return (jint) ANativeWindow_getFormat(anw); } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_setSurfaceVisualID0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_setSurfaceVisualID0 (JNIEnv *env, jclass clazz, jlong surfaceHandle, jint nativeVisualID) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; ANativeWindow_setBuffersGeometry(anw, 0, 0, nativeVisualID); } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getWidth0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getWidth0 (JNIEnv *env, jclass clazz, jlong surfaceHandle) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; return (jint) ANativeWindow_getWidth(anw); } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getHeight0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getHeight0 (JNIEnv *env, jclass clazz, jlong surfaceHandle) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; return (jint) ANativeWindow_getHeight(anw); } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_acquire0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_acquire0 (JNIEnv *env, jclass clazz, jlong surfaceHandle) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; ANativeWindow_acquire(anw); } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_release0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_release0 (JNIEnv *env, jclass clazz, jlong surfaceHandle) { ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle; ANativeWindow_release(anw); } -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_android_AndroidWindow_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_android_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { DBG_PRINT( "initIDs ok\n" ); diff --git a/src/newt/native/IntelGDL.c b/src/newt/native/IntelGDL.c index 690e1123d..a3bf101c5 100644 --- a/src/newt/native/IntelGDL.c +++ b/src/newt/native/IntelGDL.c @@ -37,9 +37,9 @@ #include #include -#include "jogamp_newt_driver_intel_gdl_Display.h" -#include "jogamp_newt_driver_intel_gdl_Screen.h" -#include "jogamp_newt_driver_intel_gdl_Window.h" +#include "jogamp_newt_driver_intel_gdl_DisplayDriver.h" +#include "jogamp_newt_driver_intel_gdl_ScreenDriver.h" +#include "jogamp_newt_driver_intel_gdl_WindowDriver.h" #include "MouseEvent.h" #include "KeyEvent.h" @@ -122,7 +122,7 @@ static void JNI_ThrowNew(JNIEnv *env, const char *throwable, const char* message * Display */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DispatchMessages +JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj, jlong displayHandle, jobject focusedWindow) { // FIXME: n/a @@ -137,7 +137,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DispatchMessage } */ } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Display_CreateDisplay +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_CreateDisplay (JNIEnv *env, jobject obj) { gdl_ret_t retval; @@ -170,7 +170,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Display_CreateDisplay return (jlong) (intptr_t) p_driver_info; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DestroyDisplay +JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_DestroyDisplay (JNIEnv *env, jobject obj, jlong displayHandle) { gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle; @@ -189,7 +189,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DestroyDisplay * Screen */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_ScreenDriver_initIDs (JNIEnv *env, jclass clazz) { screenCreatedID = (*env)->GetMethodID(env, clazz, "screenCreated", "(II)V"); @@ -201,7 +201,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_initIDs return JNI_TRUE; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_GetScreenInfo +JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_ScreenDriver_GetScreenInfo (JNIEnv *env, jobject obj, jlong displayHandle, jint idx) { gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle; @@ -233,7 +233,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_GetScreenInfo * Window */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Window_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_initIDs (JNIEnv *env, jclass clazz) { updateBoundsID = (*env)->GetMethodID(env, clazz, "updateBounds", "(IIII)V"); @@ -245,7 +245,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Window_initIDs return JNI_TRUE; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CreateSurface +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_CreateSurface (JNIEnv *env, jobject obj, jlong displayHandle, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) { gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle; @@ -338,7 +338,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CreateSurface return (jlong) (intptr_t) plane; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CloseSurface +JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_CloseSurface (JNIEnv *env, jobject obj, jlong display, jlong surface) { gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ; @@ -347,7 +347,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CloseSurface DBG_PRINT("[CloseSurface] plane %d\n", plane); } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_SetBounds0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_SetBounds0 (JNIEnv *env, jobject obj, jlong surface, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) { gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ; diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index bceb86a85..f1d6aecdf 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -44,7 +44,7 @@ #include #include -#include "jogamp_newt_driver_kd_Window.h" +#include "jogamp_newt_driver_kd_WindowDriver.h" #include "MouseEvent.h" #include "KeyEvent.h" @@ -82,7 +82,7 @@ static jmethodID sendKeyEventID = NULL; * Display */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Display_DispatchMessages +JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj) { const KDEvent * evt; @@ -180,7 +180,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Display_DispatchMessages * Window */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_Window_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs (JNIEnv *env, jclass clazz) { #ifdef VERBOSE_ON @@ -208,7 +208,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_Window_initIDs return JNI_TRUE; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_Window_CreateWindow +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_WindowDriver_CreateWindow (JNIEnv *env, jobject obj, jlong display, jlong jeglConfig) { EGLDisplay dpy = (EGLDisplay)(intptr_t)display; @@ -236,7 +236,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_Window_CreateWindow return (jlong) (intptr_t) window; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_Window_RealizeWindow +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_WindowDriver_RealizeWindow (JNIEnv *env, jobject obj, jlong window) { KDWindow *w = (KDWindow*) (intptr_t) window; @@ -251,7 +251,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_Window_RealizeWindow return (jlong) (intptr_t) nativeWindow; } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_Window_CloseWindow +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_WindowDriver_CloseWindow (JNIEnv *env, jobject obj, jlong window, jlong juserData) { KDWindow *w = (KDWindow*) (intptr_t) window; @@ -265,11 +265,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_Window_CloseWindow } /* - * Class: jogamp_newt_driver_kd_Window + * Class: jogamp_newt_driver_kd_WindowDriver * Method: setVisible0 * Signature: (JJZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Window_setVisible0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setVisible0 (JNIEnv *env, jobject obj, jlong window, jboolean visible) { KDWindow *w = (KDWindow*) (intptr_t) window; @@ -279,7 +279,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Window_setVisible0 (*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_FALSE, visible); // FIXME: or defer=true ? } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Window_setFullScreen0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setFullScreen0 (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) { /** not supported, due to missing NV property .. @@ -296,7 +296,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Window_setFullScreen0 (void)fullscreen; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_Window_setSize0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setSize0 (JNIEnv *env, jobject obj, jlong window, jint width, jint height) { KDWindow *w = (KDWindow*) (intptr_t) window; diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index bbadc9dd0..e0330a563 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -33,7 +33,7 @@ #import -#import "jogamp_newt_driver_macosx_MacWindow.h" +#import "jogamp_newt_driver_macosx_WindowDriver.h" #import "NewtMacWindow.h" #import "MouseEvent.h" @@ -155,11 +155,11 @@ NS_ENDHANDLER } /* - * Class: jogamp_newt_driver_macosx_MacDisplay + * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: initIDs * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSApplication0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSApplication0 (JNIEnv *env, jclass clazz) { static int initialized = 0; @@ -189,11 +189,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSAppli } /* - * Class: jogamp_newt_driver_macosx_MacDisplay + * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: runNSApplication0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplication0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_runNSApplication0 (JNIEnv *env, jclass clazz) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -206,11 +206,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplicatio } /* - * Class: jogamp_newt_driver_macosx_MacDisplay + * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: stopNSApplication0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_stopNSApplication0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplication0 (JNIEnv *env, jclass clazz) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -250,11 +250,11 @@ static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { } /* - * Class: jogamp_newt_driver_macosx_MacScreen + * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getWidthImpl * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getWidthImpl0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getWidthImpl0 (JNIEnv *env, jclass clazz, jint screen_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -268,11 +268,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getWidthImpl0 } /* - * Class: jogamp_newt_driver_macosx_MacScreen + * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getHeightImpl * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getHeightImpl0 (JNIEnv *env, jclass clazz, jint screen_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -318,11 +318,11 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) #define ROTMODES_PER_REALMODE 4 /* - * Class: jogamp_newt_driver_macosx_MacScreen + * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getScreenSizeMM0 * Signature: (I)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSizeMM0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenSizeMM0 (JNIEnv *env, jobject obj, jint scrn_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -367,11 +367,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSi } /* - * Class: jogamp_newt_driver_macosx_MacScreen + * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getScreenMode0 * Signature: (IIII)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenMode0 (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -459,11 +459,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo } /* - * Class: jogamp_newt_driver_macosx_MacScreen + * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: setScreenMode0 * Signature: (II)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMode0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setScreenMode0 (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx) { jboolean res = JNI_TRUE; @@ -504,11 +504,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMod } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: initIDs * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { static int initialized = 0; @@ -519,16 +519,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { - NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNamePoint); + NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't find %s", ClazzNamePoint); } pointClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==pointClz) { - NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNamePoint); + NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't use %s", ClazzNamePoint); } pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); if(NULL==pointCstr) { - NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s", + NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't fetch %s.%s %s", ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } @@ -541,11 +541,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: createWindow0 * Signature: (JIIIIZIIIJ)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0 (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask, jint bufferingType, jint screen_idx, jlong jview) { @@ -698,11 +698,11 @@ NS_ENDHANDLER /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: close0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -761,11 +761,11 @@ NS_ENDHANDLER } /* - * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: lockSurface0 * Signature: (J)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_lockSurface0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0 (JNIEnv *env, jclass clazz, jlong window) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); @@ -779,11 +779,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_lockSurface0 } /* - * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: unlockSurface0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_unlockSurface0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0 (JNIEnv *env, jclass clazz, jlong window) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); @@ -794,11 +794,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_unlockSurface0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: requestFocus0 * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 (JNIEnv *env, jobject window, jlong w, jboolean force) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -819,11 +819,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: resignFocus0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -846,11 +846,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: orderFront0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -866,11 +866,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: orderOut * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -891,11 +891,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setTitle0 * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setTitle0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0 (JNIEnv *env, jobject unused, jlong window, jstring title) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -913,11 +913,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setTitle0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: contentView * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_contentView0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -934,11 +934,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_contentView0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: changeContentView * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_changeContentView0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0 (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -977,11 +977,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_changeContentVi } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setContentSize * Signature: (JII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setContentSize0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setContentSize0 (JNIEnv *env, jobject unused, jlong window, jint w, jint h) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -998,11 +998,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setContentSize0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setFrameTopLeftPoint * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setFrameTopLeftPoint0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setFrameTopLeftPoint0 (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -1027,11 +1027,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setFrameTopLeftP } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setAlwaysOnTop0 * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setAlwaysOnTop0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTop0 (JNIEnv *env, jobject unused, jlong window, jboolean atop) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -1051,11 +1051,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setAlwaysOnTop0 } /* - * Class: jogamp_newt_driver_macosx_MacWindow + * Class: jogamp_newt_driver_macosx_WindowDriver * Method: getLocationOnScreen0 * Signature: (JII)Ljavax/media/nativewindow/util/Point; */ -JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOnScreen0 +JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0 (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) { NSObject *nsObj = (NSObject*) ((intptr_t) win); @@ -1072,11 +1072,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOn } /* - * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: setPointerVisible0 * Signature: (JZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVisible0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); @@ -1086,11 +1086,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVi } /* - * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: confinePointer0 * Signature: (JZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_confinePointer0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); @@ -1099,11 +1099,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_confinePoint } /* - * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_warpPointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 6d9c04dc3..40252f59b 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -81,9 +81,9 @@ #define DISPLAY_DEVICE_ACTIVE 0x00000001 #endif -#include "jogamp_newt_driver_windows_WindowsDisplay.h" -#include "jogamp_newt_driver_windows_WindowsScreen.h" -#include "jogamp_newt_driver_windows_WindowsWindow.h" +#include "jogamp_newt_driver_windows_DisplayDriver.h" +#include "jogamp_newt_driver_windows_ScreenDriver.h" +#include "jogamp_newt_driver_windows_WindowDriver.h" #include "Window.h" #include "MouseEvent.h" @@ -1011,11 +1011,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, } /* - * Class: jogamp_newt_driver_windows_WindowsDisplay + * Class: jogamp_newt_driver_windows_DisplayDriver * Method: DispatchMessages * Signature: ()V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMessages0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMessages0 (JNIEnv *env, jclass clazz) { int i = 0; @@ -1040,11 +1040,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMe } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: getOriginX0 * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0 (JNIEnv *env, jobject obj, jint scrn_idx) { if( GetSystemMetrics( SM_CMONITORS) > 1) { @@ -1055,11 +1055,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0 } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: getOriginY0 * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0 (JNIEnv *env, jobject obj, jint scrn_idx) { if( GetSystemMetrics( SM_CMONITORS ) > 1) { @@ -1070,11 +1070,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0 } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: getWidthImpl * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImpl0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { if( GetSystemMetrics( SM_CMONITORS) > 1) { @@ -1085,11 +1085,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImp } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: getHeightImpl * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getHeightImpl0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getHeightImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { if( GetSystemMetrics( SM_CMONITORS ) > 1) { @@ -1173,11 +1173,11 @@ static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) { } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: getScreenMode0 * Signature: (II)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getScreenMode0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScreenMode0 (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) { DISPLAY_DEVICE device; @@ -1246,11 +1246,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getScr } /* - * Class: jogamp_newt_driver_windows_WindowsScreen + * Class: jogamp_newt_driver_windows_ScreenDriver * Method: setScreenMode0 * Signature: (IIIIII)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_setScreenMode0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScreenMode0 (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot) { DISPLAY_DEVICE device; @@ -1283,11 +1283,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_setScre } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: initIDs0 * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { NewtCommon_init(env); @@ -1324,11 +1324,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: getNewtWndProc0 * Signature: ()J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_getNewtWndProc0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_getNewtWndProc0 (JNIEnv *env, jclass clazz) { return (jlong) (intptr_t) wndProc; @@ -1366,10 +1366,10 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: CreateWindow */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong hInstance, jstring jWndClassName, jstring jWndName, jlong parent, @@ -1473,11 +1473,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: MonitorFromWindow * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_MonitorFromWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_MonitorFromWindow0 (JNIEnv *env, jobject obj, jlong window) { #if (_WIN32_WINNT >= 0x0500 || _WIN32_WINDOWS >= 0x0410 || WINVER >= 0x0500) && !defined(_WIN32_WCE) @@ -1506,11 +1506,11 @@ static jboolean NewtWindows_setFullScreen(jboolean fullscreen) } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: reconfigureWindow0 * Signature: (JJIIIII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigureWindow0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jint flags) { @@ -1591,11 +1591,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: setTitle * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setTitle0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setTitle0 (JNIEnv *env, jclass clazz, jlong window, jstring title) { HWND hwnd = (HWND) (intptr_t) window; @@ -1609,11 +1609,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setTitle0 } /* - * Class: jogamp_newt_driver_windows_WindowsWindow + * Class: jogamp_newt_driver_windows_WindowDriver * Method: requestFocus * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_requestFocus0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_requestFocus0 (JNIEnv *env, jobject obj, jlong window, jboolean force) { DBG_PRINT("*** WindowsWindow: RequestFocus0\n"); @@ -1621,11 +1621,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_requestFocu } /* - * Class: Java_jogamp_newt_driver_windows_WindowsWindow + * Class: Java_jogamp_newt_driver_windows_WindowDriver * Method: setPointerVisible0 * Signature: (JJZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setPointerVisible0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible) { HWND hwnd = (HWND) (intptr_t) window; @@ -1660,11 +1660,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setPoin } /* - * Class: Java_jogamp_newt_driver_windows_WindowsWindow + * Class: Java_jogamp_newt_driver_windows_WindowDriver * Method: confinePointer0 * Signature: (JJZIIII)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_confinePointer0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine, jint l, jint t, jint r, jint b) { HWND hwnd = (HWND) (intptr_t) window; @@ -1686,11 +1686,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_confine } /* - * Class: Java_jogamp_newt_driver_windows_WindowsWindow + * Class: Java_jogamp_newt_driver_windows_WindowDriver * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_warpPointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { DBG_PRINT( "*** WindowsWindow: warpPointer0: %d/%d\n", x, y); @@ -1698,11 +1698,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_warpPointer } /* - * Class: Java_jogamp_newt_driver_windows_WindowsWindow + * Class: Java_jogamp_newt_driver_windows_WindowDriver * Method: trackPointerLeave0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_trackPointerLeave0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_trackPointerLeave0 (JNIEnv *env, jclass clazz, jlong window) { HWND hwnd = (HWND) (intptr_t) window; diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h index 982255b8a..128b6b6f1 100644 --- a/src/newt/native/X11Common.h +++ b/src/newt/native/X11Common.h @@ -45,9 +45,9 @@ #include -#include "jogamp_newt_driver_x11_X11Screen.h" -#include "jogamp_newt_driver_x11_X11Display.h" -#include "jogamp_newt_driver_x11_X11Window.h" +#include "jogamp_newt_driver_x11_ScreenDriver.h" +#include "jogamp_newt_driver_x11_DisplayDriver.h" +#include "jogamp_newt_driver_x11_WindowDriver.h" #include "Window.h" #include "MouseEvent.h" diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index ce7d9a0e1..3157538c3 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -34,7 +34,7 @@ jclass X11NewtWindowClazz = NULL; jmethodID insetsChangedID = NULL; jmethodID visibleChangedID = NULL; -static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/X11Window"; +static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; static jmethodID displayCompletedID = NULL; @@ -264,11 +264,11 @@ static jint X11InputState2NewtModifiers(unsigned int xstate) { */ /* - * Class: jogamp_newt_driver_x11_X11Display + * Class: jogamp_newt_driver_x11_DisplayDriver * Method: initIDs * Signature: (Z)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 (JNIEnv *env, jclass clazz, jboolean debug) { jclass c; @@ -281,12 +281,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 if(NULL==X11NewtWindowClazz) { c = (*env)->FindClass(env, ClazzNameX11NewtWindow); if(NULL==c) { - NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameX11NewtWindow); + NewtCommon_FatalError(env, "NEWT X11Display: can't find %s", ClazzNameX11NewtWindow); } X11NewtWindowClazz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==X11NewtWindowClazz) { - NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameX11NewtWindow); + NewtCommon_FatalError(env, "NEWT X11Display: can't use %s", ClazzNameX11NewtWindow); } } @@ -331,11 +331,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 } /* - * Class: jogamp_newt_driver_x11_X11Display + * Class: jogamp_newt_driver_x11_DisplayDriver * Method: CompleteDisplay * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay0 (JNIEnv *env, jobject obj, jlong display) { Display * dpy = (Display *)(intptr_t)display; @@ -366,11 +366,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0 } /* - * Class: jogamp_newt_driver_x11_X11Display + * Class: jogamp_newt_driver_x11_DisplayDriver * Method: DisplayRelease0 * Signature: (JJJ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0 (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) { Display * dpy = (Display *)(intptr_t)display; @@ -390,11 +390,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0 } /* - * Class: jogamp_newt_driver_x11_X11Display + * Class: jogamp_newt_driver_x11_DisplayDriver * Method: DispatchMessages * Signature: (JIJJ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) { Display * dpy = (Display *) (intptr_t) display; diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c index 698eed89d..334c39727 100644 --- a/src/newt/native/X11Screen.c +++ b/src/newt/native/X11Screen.c @@ -36,11 +36,11 @@ #endif /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: GetScreen * Signature: (JI)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_GetScreen0 (JNIEnv *env, jclass clazz, jlong display, jint screen_index) { Display * dpy = (Display *)(intptr_t)display; @@ -60,14 +60,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 return (jlong) (intptr_t) scrn; } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getWidth0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display * dpy = (Display *) (intptr_t) display; return (jint) DisplayWidth( dpy, scrn_idx); } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display * dpy = (Display *) (intptr_t) display; @@ -112,11 +112,11 @@ static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getAvailableScreenModeRotations0 * Signature: (JI)I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -162,11 +162,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableSc } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getNumScreenModeResolution0 * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -177,7 +177,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeRes #endif if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); + DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0: RANDR not available\n"); return 0; } @@ -200,17 +200,17 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeRes } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getScreenModeResolutions0 * Signature: (JII)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) { Display *dpy = (Display *) (intptr_t) display; if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); + DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0: RANDR not available\n"); return (*env)->NewIntArray(env, 0); } @@ -242,17 +242,17 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeR } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getScreenModeRates0 * Signature: (JII)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) { Display *dpy = (Display *) (intptr_t) display; if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); + DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0: RANDR not available\n"); return (*env)->NewIntArray(env, 0); } @@ -285,11 +285,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeR } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getScreenConfiguration0 * Signature: (JI)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenConfiguration0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -301,7 +301,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenConfigura #endif if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenConfiguration0: RANDR not available\n"); + DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0: RANDR not available\n"); return 0; } #ifdef DBG_PERF @@ -320,22 +320,22 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenConfigura } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: freeScreenConfiguration0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Screen_freeScreenConfiguration0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_freeScreenConfiguration0 (JNIEnv *env, jclass clazz, jlong screenConfiguration) { XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration ); } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getCurrentScreenRate0 * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0 (JNIEnv *env, jclass clazz, jlong screenConfiguration) { XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration; @@ -347,11 +347,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRat } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getCurrentScreenRotation0 * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0 (JNIEnv *env, jclass clazz, jlong screenConfiguration) { XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration; @@ -364,11 +364,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRot /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: getCurrentScreenResolutionIndex0 * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0 (JNIEnv *env, jclass clazz, jlong screenConfiguration) { XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration; @@ -383,11 +383,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRes } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: setCurrentScreenModeStart0 * Signature: (JIJIII)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation) { Display *dpy = (Display *) (intptr_t) display; @@ -432,11 +432,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScree } /* - * Class: jogamp_newt_driver_x11_X11Screen + * Class: jogamp_newt_driver_x11_ScreenDriver * Method: setCurrentScreenModePollEnd0 * Signature: (J)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) { Display *dpy = (Display *) (intptr_t) display; @@ -445,7 +445,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScree XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); + DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0: RANDR not available\n"); return JNI_FALSE; } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index daf9f2b53..59862f463 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -467,11 +467,11 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, */ /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: initIDs * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { return JNI_TRUE; @@ -505,10 +505,10 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CreateWindow */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jint visualID, jlong javaObjectAtom, jlong windowDeleteAtom, @@ -666,11 +666,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CloseWindow * Signature: (JJ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom) { Display * dpy = (Display *) (intptr_t) display; @@ -703,7 +703,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0 NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1); // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom); XDestroyWindow(dpy, w); XSync(dpy, False); @@ -729,11 +729,11 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { */ /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: reconfigureWindow0 * Signature: (JIJJIIIII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0 (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, jlong jparent, jlong jwindow, jlong windowDeleteAtom, jint x, jint y, jint width, jint height, jint flags) @@ -869,33 +869,33 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: requestFocus0 * Signature: (JJZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_requestFocus0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0 (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force) { NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ; } /* - * Class: jogamp_newt_driver_x11_X11Window + * Class: jogamp_newt_driver_x11_WindowDriver * Method: getParentWindow0 * Signature: (JJ)J */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_getParentWindow0 +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow0 (JNIEnv *env, jclass clazz, jlong display, jlong window) { return (jlong) NewtWindows_getParent ((Display *) (intptr_t) display, (Window)window); } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: setTitle0 * Signature: (JJLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title) { Display * dpy = (Display *) (intptr_t) display; @@ -942,11 +942,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0 } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: setPointerVisible0 * Signature: (JJZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisible0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean mouseVisible) { static char noData[] = { 0,0,0,0,0,0,0,0 }; @@ -976,11 +976,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisib } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: confinePointer0 * Signature: (JJZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean confine) { Display * dpy = (Display *) (intptr_t) display; @@ -999,11 +999,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0 } /* - * Class: Java_jogamp_newt_driver_x11_X11Window + * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_warpPointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y) { Display * dpy = (Display *) (intptr_t) display; diff --git a/src/newt/native/bcm_egl.c b/src/newt/native/bcm_egl.c index 79ebd20e0..9b960d278 100644 --- a/src/newt/native/bcm_egl.c +++ b/src/newt/native/bcm_egl.c @@ -37,7 +37,7 @@ #include #include -#include "jogamp_newt_driver_bcm_egl_Window.h" +#include "jogamp_newt_driver_bcm_egl_WindowDriver.h" #include "MouseEvent.h" #include "KeyEvent.h" @@ -67,7 +67,7 @@ static jmethodID windowCreatedID = NULL; * Display */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Display_DispatchMessages +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj) { // FIXME: n/a @@ -75,7 +75,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Display_DispatchMessages (void) obj; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_Display_CreateDisplay +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_CreateDisplay (JNIEnv *env, jobject obj, jint width, jint height) { (void) env; @@ -89,7 +89,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_Display_CreateDisplay return (jlong) (intptr_t) dpy; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Display_DestroyDisplay +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_DestroyDisplay (JNIEnv *env, jobject obj, jlong display) { EGLDisplay dpy = (EGLDisplay)(intptr_t)display; @@ -106,7 +106,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Display_DestroyDisplay * Window */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_egl_Window_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_initIDs (JNIEnv *env, jclass clazz) { windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(III)V"); @@ -118,7 +118,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_egl_Window_initIDs return JNI_TRUE; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_Window_CreateWindow +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_CreateWindow (JNIEnv *env, jobject obj, jlong display, jboolean chromaKey, jint width, jint height) { EGLDisplay dpy = (EGLDisplay)(intptr_t)display; @@ -162,7 +162,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_Window_CreateWindow return (jlong) (intptr_t) window; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Window_CloseWindow +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_CloseWindow (JNIEnv *env, jobject obj, jlong display, jlong window) { EGLDisplay dpy = (EGLDisplay) (intptr_t) display; @@ -175,7 +175,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Window_CloseWindow DBG_PRINT( "[CloseWindow] X\n"); } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_Window_SwapWindow +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_SwapWindow (JNIEnv *env, jobject obj, jlong display, jlong window) { EGLDisplay dpy = (EGLDisplay) (intptr_t) display; diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c index 09ab8a634..e41745e14 100644 --- a/src/newt/native/bcm_vc_iv.c +++ b/src/newt/native/bcm_vc_iv.c @@ -32,9 +32,9 @@ #include "bcm_vc_iv.h" -#include "jogamp_newt_driver_bcm_vc_iv_Display.h" -#include "jogamp_newt_driver_bcm_vc_iv_Screen.h" -#include "jogamp_newt_driver_bcm_vc_iv_Window.h" +#include "jogamp_newt_driver_bcm_vc_iv_DisplayDriver.h" +#include "jogamp_newt_driver_bcm_vc_iv_ScreenDriver.h" +#include "jogamp_newt_driver_bcm_vc_iv_WindowDriver.h" #define VERBOSE_ON 1 @@ -57,7 +57,7 @@ static jmethodID sendKeyEventID = NULL; * Display */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Display_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_initIDs (JNIEnv *env, jclass clazz) { bcm_host_init(); @@ -66,7 +66,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Display_initIDs return JNI_TRUE; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Display_DispatchMessages +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj) { } @@ -75,7 +75,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Display_DispatchMessage * Screen */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Screen_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initIDs (JNIEnv *env, jclass clazz) { uint32_t screen_width; @@ -91,7 +91,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Screen_initIDs return JNI_TRUE; } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Screen_initNative +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative (JNIEnv *env, jobject obj) { uint32_t screen_width; @@ -109,7 +109,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Screen_initNative * Window */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_initIDs +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initIDs (JNIEnv *env, jclass clazz) { windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); @@ -131,7 +131,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_initIDs return JNI_TRUE; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_CreateWindow +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow (JNIEnv *env, jobject obj, jint width, jint height) { int32_t success = 0; @@ -166,13 +166,13 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_CreateWindow return (jlong) (intptr_t) nativeWindowPtr; } -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_RealizeWindow +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_RealizeWindow (JNIEnv *env, jobject obj, jlong window) { return (jlong) (intptr_t) 0; } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_CloseWindow +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow (JNIEnv *env, jobject obj, jlong window, jlong juserData) { EGL_DISPMANX_WINDOW_T * nativeWindowPtr = (EGL_DISPMANX_WINDOW_T *) (intptr_t) window ; @@ -181,21 +181,21 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_CloseWindow } /* - * Class: jogamp_newt_driver_bcm_vc_iv_Window + * Class: jogamp_newt_driver_bcm_vc_iv_WindowDriver * Method: setVisible0 * Signature: (JJZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_setVisible0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setVisible0 (JNIEnv *env, jobject obj, jlong window, jboolean visible) { } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_setFullScreen0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setFullScreen0 (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) { } -JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_Window_setSize0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setSize0 (JNIEnv *env, jobject obj, jlong window, jint width, jint height) { // FIXME RESIZE (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE); diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java index 11babf187..89395e309 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java @@ -34,11 +34,11 @@ import java.util.Arrays; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; @@ -55,8 +55,8 @@ public class MovieSimpleActivity0 extends NewtBaseActivity { MouseAdapter toFrontMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { Object src = e.getSource(); - if(src instanceof AndroidWindow) { - ((AndroidWindow)src).requestFocus(false); + if(src instanceof Window) { + ((Window)src).requestFocus(false); } } }; diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java index a5e5f4ccb..a7fefd838 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java @@ -36,11 +36,11 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; @@ -59,8 +59,8 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { MouseAdapter toFrontMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { Object src = e.getSource(); - if(src instanceof AndroidWindow) { - ((AndroidWindow)src).requestFocus(false); + if(src instanceof Window) { + ((Window)src).requestFocus(false); } } }; @@ -121,7 +121,7 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); { final int padding = mPlayerHUD ? 32 : 0; - final android.view.View androidView = ((AndroidWindow)glWindowMain.getDelegatedWindow()).getAndroidView(); + final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowMain.getDelegatedWindow()).getAndroidView(); glWindowMain.setSize(scrn.getWidth()-padding, scrn.getHeight()-padding); glWindowMain.setUndecorated(true); // setContentView(getWindow(), glWindowMain); @@ -168,7 +168,7 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { viewGroup.post(new Runnable() { public void run() { - final android.view.View androidView = ((AndroidWindow)glWindowHUD.getDelegatedWindow()).getAndroidView(); + final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowHUD.getDelegatedWindow()).getAndroidView(); // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight(), Gravity.TOP|Gravity.LEFT)); registerNEWTWindow(glWindowHUD); -- cgit v1.2.3 From 4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 15 Sep 2012 16:54:52 +0200 Subject: Seamless Integration of an FBObject based GLFBODrawable as GLOffscreenAutoDrawable.FBO and as an OffscreenLayerSurface's drawable (OSX) - Fix Bugs 569 and 599 Summary: ========= The new FBObject based GLFBODrawable implementation allows the seamless utilization of FBO offscreen rendering in single buffer, double buffer and MSAA mode. The GLFBODrawable uses a parent drawable based on a dummy surface to allow a GLOffscreenAutoDrawable.FBO creation or a mutable surface supporting an existing offscreen layer surface (OSX CALayer). Offscreen GLDrawable's and GLOffscreenAutoDrawable's can be selected via the GLCapabilities. If simply !onscreen is selected in the caps instance w/o enabling FBO, PBuffer or Bitmap, the factory will automatically choose regarding availability: FBO > PBuffer > Bitmap Double buffering is supported in MSAA more (intrinsic) and explicit in non MSAA. It is preferred when delivering resources (texture id's or framebuffer names) to a shared GLContext. This is demonstrated in (emulates our OSX CALayer implementation): TestFBOOffThreadSharedContextMix2DemosES2NEWT, TestFBOOnThreadSharedContext1DemoES2NEWT and with the OSX JAWT OffscreenLayerSurface itself. FBO is the preferred choice. +++ Offscreen drawables can be resized while maintaining a bound GLContext (e.g. w/ GLAutoDrawable). Previously both, drawable and context, needed to be destroyed and recreated at offscreen resize. Common implementation in GLDrawableHelper is used in the implementations (NEWT's GLWindow, AWT GLCanvas, SWT GLCanvas). +++ Tested: ======= Manually run all unit tests on: - Linux x86_64 NVidia/AMD/Mesa3d(ES) - OSX x86_64 NVidia - Windows x86_64 NVidia - Android arm Mali-400/Tegra-2 No regressions. Disclaimer: =========== This feature is committed almost in one patch. Both previous commits were introducing / fixing the capabilities behavior: 90d45928186f2be99999461cfe45f76a783cc961 9036376b7806a5fc61590bf49404eb71830de92f I have to appologize for the huge size and impact (files and platforms) of this commit however, I could not find a better way to inject this feature in one sane piece. NativeWindow Details: ===================== Complete decoupling of platform impl. detail of surfaces implementing ProxySurface. Used to generalize dummy surfaces and EGL surfaces on top of a native platform surface. - ProxySurface.UpstreamSurfaceHook -> UpstreamSurfaceHook - abstract class ProxySurface -> interface ProxySurface + ProxySurfaceImpl - Misc. implementations JOGL Details: ===================== FBOObject: API Change / Simplification & Usability - Removed reference counter to remove complexity, allow user to choose. - Add 'dispose' flag for detachColorbuffer(..), allowing to keep attachment alive - Fix equals operation of Attachment - Check pre-exising GL errors - Interface Colobuffer gets lifecycle methods - Add static factory methods to create Attachments w/o FBObject instance - Reset: - Clip min size to 1 - Keep alive samplingSink, i.e. don't issue resetMSAATexture2DSink(..). It gets called at syncFramebuffer()/use(..) later on before actual usage. This allows the consumer to utilize the GL_FRONT buffer until (e.g.) swap. - misc bugfixes GLOffscreenAutoDrawable: API Change - Reloc and interfacing - class com.jogamp.opengl.OffscreenAutoDrawable -> javax.media.opengl.* interfaces GLOffscreenAutoDrawable extends GLAutoDrawable GLOffscreenAutoDrawable.FBO extends GLOffscreenAutoDrawable, GLFBODrawable - Added general implementation and FBO specialization - Replacing GLPBuffer (deprecated) .. usable for any offscreen GLDrawable via factory GLAutoDrawable: - Add 'GLDrawable getDelegatedDrawable()' - Refine documentation of setContext(..), remove disclaimer and fixme tags GLDrawableFactory: - Refine API doc and it's selection mechanism for offscreen. - Add createOffscreenDrawable(..) - Add createOffscreenAutoDrawable(..) - Add canCreateFBO(..) - Mark createGLPbuffer(..) deprectated Mark GLPBuffer deprecated New: GLFBODrawable extends GLDrawable GLCanvas (AWT and SWT): Add offscreen resize support w/o GLContext recreation GLAutoDrawableBase .. GLWindow: - Add offscreen resize support w/o GLContext recreation - Remove double swapBuffer call - GLBase/GLContext: - Add: - boolean hasBasicFBOSupport() - boolean hasFullFBOSupport() - int getMaxRenderbufferSamples() - boolean isTextureFormatBGRA8888Available() GLContext: Fix version detection and hasGLSL() - Version detection in setGLFunctionAvailability(..) - Query GL_VERSION ASAP and parse it and compare w/ given major/minor - Use parsed version if valid and lower than given _or_ given is invalid. - Use validated version for caching (procaddr, ..), version number, etc. - Fix hasGLSL() Since 'isGL2ES2()' is true if 'isGL2()' and the latter simply alows GL 1.*, we confine the result to a GL >= 2.0 on desktops. FIXME: May consider GL 1.5 w/ extensions. - return isGL2ES2(); + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; GLDrawableImpl: - Add 'associateContext(GLContext, boolean)' allowing impl. to have a (weak) reference list of bound context. This is was pulled up from the OSX specific drawable impl. - swapBuffersImpl() -> swapBuffersImpl(boolean doubleBuffered) and call it regardless of single buffering. This is required to propagate this event to impl. properly, i.e. FBODrawable requires a swap notification. - Clarify 'contextMadeCurrent(..)' protocol GLDrawableHelper: - Add resize and recreate offscreen drawable util method - Simplify required init/reshape calls for GLEventListener - GLGraphicsConfigurationUtil: - fixWinAttribBitsAndHwAccel: Reflect sharede context hw-accel bits - OSX has no offscreen bitmap, use pbuffer - use proper offscreen auto selection if offscreen and no modes are set EGL Context/Drawable/DrawableFactory: Abstract native platform code out of base classes - Use EGLWrappedSurface w/ UpstreamSurfaceHook to handle upstream (X11, WGL, ..) lifecycle - in case the EGL resource is hooked up on it. Invisible dummy surfaces: All platforms - size is now reduced to 64x64 and decoupled of actual generic mutable size - fix device lifecycle, no more leaks +++ OSX ==== Enable support for GLFBODrawableImpl in offscreen CALayer mode - NSOpenGLImpl: hooks to calayer native code - calayer code: - allows pbuffer and texures (FBO) - decouple size and draw calls avoiding flickering - enable auto resize of calayer tree MacOSXCGLContext: - NSOpenGLImpl: - Fix false pbuffer 'usage', validate the pointer - If !pbuffer, copy other window mode bits of caps - MacOSXCGLGraphicsConfiguration: - Only assume pbuffer if !onscreen - Remove reference of native pixelformat pointer Native code: - use 'respondsToSelector:' query before calling 'new' methods avoiding an error message where unsuported (prev. OSX versions) - if monitor refresh-rate is queried 0, set to default 60hz - add missing NSAutoreleasePool decoration +++ Android / NEWT: =============== Issue setVisible(..) w/o wait, i.e. queue on EDT, @Android surfaceChanged() callback. Otherwise we could deadlock: setVisible(..) -> EDT -> setVisibleImpl(..) -> 'GL-display'. the latter may may cause havoc while Android-EDT is blocked [until it's return]. --- doc/TODO.txt | 12 - make/build-jogl.xml | 2 +- .../config/jogl/gl-impl-CustomJavaCode-common.java | 20 + make/scripts/java-win64-dbg.bat | 4 +- make/scripts/tests-x64.bat | 45 +- make/scripts/tests.sh | 50 +- make/stub_includes/opengl/macosx-window-system.h | 11 +- src/jogl/classes/com/jogamp/opengl/FBObject.java | 882 +++++++++++++-------- .../com/jogamp/opengl/GLAutoDrawableDelegate.java | 189 +++++ .../classes/com/jogamp/opengl/GLExtensions.java | 3 + .../com/jogamp/opengl/OffscreenAutoDrawable.java | 112 --- .../classes/com/jogamp/opengl/swt/GLCanvas.java | 41 +- .../classes/javax/media/opengl/GLAutoDrawable.java | 38 +- .../javax/media/opengl/GLAutoDrawableDelegate.java | 144 ---- src/jogl/classes/javax/media/opengl/GLBase.java | 38 + src/jogl/classes/javax/media/opengl/GLContext.java | 97 ++- .../javax/media/opengl/GLDrawableFactory.java | 128 ++- .../classes/javax/media/opengl/GLFBODrawable.java | 173 ++++ .../media/opengl/GLOffscreenAutoDrawable.java | 63 ++ src/jogl/classes/javax/media/opengl/GLPbuffer.java | 6 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 119 +-- .../classes/javax/media/opengl/awt/GLJPanel.java | 13 +- .../classes/jogamp/opengl/GLAutoDrawableBase.java | 76 +- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 175 ++-- .../jogamp/opengl/GLDrawableFactoryImpl.java | 127 +-- .../classes/jogamp/opengl/GLDrawableHelper.java | 185 ++++- src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 80 +- .../classes/jogamp/opengl/GLFBODrawableImpl.java | 496 ++++++++++-- .../jogamp/opengl/GLGraphicsConfigurationUtil.java | 28 +- .../jogamp/opengl/GLOffscreenAutoDrawableImpl.java | 123 +++ src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 31 +- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 6 - .../classes/jogamp/opengl/egl/EGLDrawable.java | 135 ++-- .../jogamp/opengl/egl/EGLDrawableFactory.java | 163 +--- .../opengl/egl/EGLDummyUpstreamSurfaceHook.java | 49 ++ .../jogamp/opengl/egl/EGLExternalContext.java | 11 - .../jogamp/opengl/egl/EGLGLCapabilities.java | 5 +- .../opengl/egl/EGLGraphicsConfiguration.java | 9 +- .../jogamp/opengl/egl/EGLOnscreenContext.java | 11 - .../jogamp/opengl/egl/EGLOnscreenDrawable.java | 4 +- .../jogamp/opengl/egl/EGLPbufferContext.java | 10 - .../jogamp/opengl/egl/EGLPbufferDrawable.java | 8 +- .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java | 145 +++- .../jogamp/opengl/egl/EGLWrappedSurface.java | 26 + .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 716 ++++++++++------- .../opengl/macosx/cgl/MacOSXCGLDrawable.java | 48 +- .../macosx/cgl/MacOSXCGLDrawableFactory.java | 71 +- .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 21 +- .../cgl/MacOSXCGLGraphicsConfigurationFactory.java | 2 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 7 +- .../macosx/cgl/MacOSXOnscreenCGLDrawable.java | 4 +- .../opengl/macosx/cgl/MacOSXPbufferCGLContext.java | 1 + .../macosx/cgl/MacOSXPbufferCGLDrawable.java | 42 +- .../windows/wgl/WindowsExternalWGLContext.java | 4 +- .../windows/wgl/WindowsExternalWGLDrawable.java | 4 +- .../opengl/windows/wgl/WindowsWGLDrawable.java | 43 +- .../windows/wgl/WindowsWGLDrawableFactory.java | 58 +- .../wgl/WindowsWGLGraphicsConfiguration.java | 29 +- .../WindowsWGLGraphicsConfigurationFactory.java | 28 +- .../opengl/x11/glx/X11ExternalGLXContext.java | 4 +- .../opengl/x11/glx/X11ExternalGLXDrawable.java | 5 +- .../jogamp/opengl/x11/glx/X11GLXDrawable.java | 7 +- .../opengl/x11/glx/X11GLXDrawableFactory.java | 63 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 6 +- .../glx/X11GLXGraphicsConfigurationFactory.java | 6 +- .../opengl/x11/glx/X11PbufferGLXDrawable.java | 17 +- .../macosx/MacOSXWindowSystemInterface-calayer.m | 665 ++++++++++++++++ .../macosx/MacOSXWindowSystemInterface-pbuffer.m | 494 ------------ .../native/macosx/MacOSXWindowSystemInterface.m | 40 +- .../DelegatedUpstreamSurfaceHookMutableSize.java | 39 + ...elegatedUpstreamSurfaceHookWithSurfaceSize.java | 54 ++ .../UpstreamSurfaceHookMutableSize.java | 45 ++ .../com/jogamp/nativewindow/WrappedSurface.java | 78 -- .../com/jogamp/nativewindow/awt/JAWTWindow.java | 99 ++- .../jogamp/nativewindow/egl/EGLGraphicsDevice.java | 4 +- .../javax/media/nativewindow/NativeSurface.java | 5 +- .../media/nativewindow/OffscreenLayerSurface.java | 3 + .../javax/media/nativewindow/ProxySurface.java | 266 ++----- .../media/nativewindow/UpstreamSurfaceHook.java | 52 ++ .../jogamp/nativewindow/ProxySurfaceImpl.java | 326 ++++++++ .../jogamp/nativewindow/WrappedSurface.java | 95 +++ .../nativewindow/jawt/macosx/MacOSXJAWTWindow.java | 84 +- .../macosx/OSXDummyUpstreamSurfaceHook.java | 56 ++ .../jogamp/nativewindow/macosx/OSXUtil.java | 15 + .../windows/GDIDummyUpstreamSurfaceHook.java | 50 ++ .../jogamp/nativewindow/windows/GDISurface.java | 34 +- .../x11/X11DummyUpstreamSurfaceHook.java | 60 ++ src/nativewindow/native/macosx/OSXmisc.m | 189 +++-- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 9 + .../classes/com/jogamp/newt/opengl/GLWindow.java | 25 +- .../classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 3 + src/newt/classes/jogamp/newt/OffscreenWindow.java | 31 +- src/newt/classes/jogamp/newt/WindowImpl.java | 34 +- .../jogamp/newt/driver/android/WindowDriver.java | 2 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 24 +- src/newt/native/MacWindow.m | 49 +- .../test/android/MovieCubeActivityLauncher0.java | 2 + .../android/NEWTGraphUI1pActivityLauncher.java | 22 +- .../jogl/acore/TestFBOAutoDrawableDeadlockAWT.java | 128 +++ .../jogl/acore/TestFBOAutoDrawableFactoryNEWT.java | 375 +++++++++ .../test/junit/jogl/acore/TestFBODrawableNEWT.java | 272 ------- .../test/junit/jogl/acore/TestFBOMRTNEWT01.java | 2 +- .../junit/jogl/acore/TestFBOMix2DemosES2NEWT.java | 2 +- ...tFBOOffThreadSharedContextMix2DemosES2NEWT.java | 298 +++++++ .../TestFBOOnThreadSharedContext1DemoES2NEWT.java | 273 +++++++ .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 152 ---- ...estGLAutoDrawableDelegateOnOffscrnCapsNEWT.java | 384 +++++++++ .../TestGLAutoDrawableFactoryOffscrnCapsNEWT.java | 317 ++++++++ ...TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java | 328 ++++++++ ...estGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java | 351 ++++++++ ...LAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java | 300 +++++++ .../junit/jogl/acore/TestGLCapabilities01NEWT.java | 266 ------- .../acore/TestGLContextDrawableSwitchNEWT.java | 22 +- .../junit/jogl/acore/TestGLDrawable01NEWT.java | 171 ---- .../jogl/acore/TestGLExtensionQueryOffscreen.java | 19 +- .../jogl/acore/TestNEWTCloseX11DisplayBug565.java | 46 +- .../acore/TestOffscreenLayer01GLCanvasAWT.java | 236 ++++++ .../acore/TestOffscreenLayer02NewtCanvasAWT.java | 233 ++++++ .../junit/jogl/acore/TestPBufferDeadlockAWT.java | 2 + .../junit/jogl/acore/TestSharedContextListAWT.java | 20 +- .../jogl/acore/TestSharedContextListNEWT.java | 20 +- .../jogl/acore/TestSharedContextListNEWT2.java | 14 +- .../jogl/acore/TestSharedContextNewtAWTBug523.java | 17 +- .../jogl/acore/TestSharedContextVBOES1NEWT.java | 20 +- .../jogl/acore/TestSharedContextVBOES2NEWT.java | 20 +- .../jogl/acore/TestSharedContextVBOES2NEWT2.java | 14 +- .../awt/TestBug461FBOSupersamplingSwingAWT.java | 159 ++++ .../TestBug461OffscreenSupersamplingSwingAWT.java | 157 ---- .../TestBug461PBufferSupersamplingSwingAWT.java | 159 ++++ .../junit/jogl/caps/TestMultisampleES1AWT.java | 2 +- .../junit/jogl/caps/TestMultisampleES1NEWT.java | 2 +- .../junit/jogl/caps/TestMultisampleES2NEWT.java | 2 +- .../opengl/test/junit/jogl/demos/es1/GearsES1.java | 6 + .../test/junit/jogl/demos/es1/RedSquareES1.java | 19 +- .../test/junit/jogl/demos/es2/FBOMix2DemosES2.java | 5 +- .../opengl/test/junit/jogl/demos/es2/GearsES2.java | 17 +- .../test/junit/jogl/demos/es2/Mix2TexturesES2.java | 216 +++++ .../test/junit/jogl/demos/es2/RedSquareES2.java | 21 +- .../junit/jogl/demos/es2/awt/TestGearsES2AWT.java | 27 +- .../opengl/test/junit/jogl/demos/gl2/Gears.java | 13 +- .../jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java | 2 +- .../test/junit/jogl/offscreen/ReadBufferBase.java | 2 +- .../test/junit/jogl/swt/TestNewtCanvasSWTGLn.java | 2 +- .../junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java | 2 +- .../TestGLReadBufferUtilTextureIOWrite01AWT.java | 4 +- .../TestGLReadBufferUtilTextureIOWrite01NEWT.java | 16 +- .../TestGLReadBufferUtilTextureIOWrite02AWT.java | 2 +- .../TestGLReadBufferUtilTextureIOWrite02NEWT.java | 2 +- .../util/texture/TestPNGTextureFromFileAWT.java | 2 +- .../util/texture/TestPNGTextureFromFileNEWT.java | 2 +- .../test/junit/newt/TestFocus01SwingAWTRobot.java | 21 +- .../test/junit/newt/TestFocus02SwingAWTRobot.java | 16 +- .../opengl/test/junit/newt/TestWindows01NEWT.java | 1 - .../parenting/NewtAWTReparentingKeyAdapter.java | 2 +- .../TestParentingOffscreenLayer01GLCanvasAWT.java | 211 ----- ...TestParentingOffscreenLayer02NewtCanvasAWT.java | 221 ------ .../opengl/test/junit/util/AWTRobotUtil.java | 39 +- .../opengl/test/junit/util/NEWTGLContext.java | 4 +- .../jogamp/opengl/test/junit/util/UITestCase.java | 109 ++- 159 files changed, 9357 insertions(+), 4643 deletions(-) create mode 100644 src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java delete mode 100644 src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java create mode 100644 src/jogl/classes/javax/media/opengl/GLFBODrawable.java create mode 100644 src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java create mode 100644 src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java create mode 100644 src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m delete mode 100644 src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java delete mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java create mode 100644 src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461OffscreenSupersamplingSwingAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer02NewtCanvasAWT.java (limited to 'src/newt/native/MacWindow.m') diff --git a/doc/TODO.txt b/doc/TODO.txt index 20a7a9071..0ce1fd3ac 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -1,13 +1,6 @@ Version 2.0: -- Fix ES2 detection if it fails (no egl pbuffer on nokia es2) ? - SIGG slides / video -- FBO Drawable w/ given NativeSurface - and OSX w/ JAWT - - Bug 569 - - Bug 599 - -- cleanup jocl build/jar/demos -- clean up . in jar names in all docs and tutorials - ES3 / GL 4.3 @@ -15,11 +8,6 @@ Version 2.0: WIP: -- GLPbuffer -> GLOffscreenAutoDrawable - - GLPbuffer GLDrawableFactory.createPbuffer() -> - GLOffscreenAutoDrawable GLDrawableFactory.createOffsceenAutoDrawable() - - Mark both deprecated! - - Optimize/Fix NIO caching of glMapBuffer/glUnmapBuffer - optimize the NIO caching, i.e. memory range, incr. reference count - _remove_ the cached object w/ decr. ref count, remove object diff --git a/make/build-jogl.xml b/make/build-jogl.xml index 40859845c..a72d6c77c 100644 --- a/make/build-jogl.xml +++ b/make/build-jogl.xml @@ -1375,7 +1375,7 @@ - + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index b05ba2643..283a4e623 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -50,6 +50,26 @@ return null; } + @Override + public final boolean hasBasicFBOSupport() { + return _context.hasBasicFBOSupport(); + } + + @Override + public final boolean hasFullFBOSupport() { + return _context.hasFullFBOSupport(); + } + + @Override + public final int getMaxRenderbufferSamples() { + return _context.getMaxRenderbufferSamples(); + } + + @Override + public final boolean isTextureFormatBGRA8888Available() { + return _context.isTextureFormatBGRA8888Available(); + } + @Override public final GLContext getContext() { return _context; diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index 510ebf4dc..b63438534 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -30,13 +30,15 @@ REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dn REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.ExtensionAvailabilityCache" "-Djogamp.debug.ProcAddressHelper=true" REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" +REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.GLDrawable" "-Dnativewindow.debug.GraphicsConfiguration" REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.Lock" "-Djogamp.debug.Lock.TraceLock" -set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Djogl.debug=all" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" +set D_ARGS="-Dnewt.debug.Window" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 22cce49aa..a4207b696 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -1,9 +1,9 @@ REM scripts\java-win64-dbg.bat jogamp.newt.awt.opengl.VersionApplet REM scripts\java-win64-dbg.bat com.jogamp.newt.opengl.GLWindow REM scripts\java-win64-dbg.bat javax.media.opengl.awt.GLCanvas -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT $* -scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn @@ -40,13 +40,13 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestP REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT @@ -73,9 +73,9 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultis REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461OffscreenSupersamplingSwingAWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %* @@ -96,16 +96,25 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtD REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02 -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT %* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT +scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* + +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableOffThreadSharedContextES2NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index ce04ae4dc..d2e2db375 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -32,7 +32,7 @@ MOSX=0 MOSX_MT=0 uname -a | grep -i Darwin && MOSX=1 if [ $MOSX -eq 1 ] ; then - #export NSZombieEnabled=YES + export NSZombieEnabled=YES MOSX_MT=1 fi @@ -56,11 +56,13 @@ function jrun() { #D_ARGS="-Djogl.disable.opengles" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.GLSLCode -Dnewt.debug.Window.MouseEvent" #D_ARGS="-Djogl.debug.TraceGL -Djogl.debug.DebugGL -Djogl.debug.GLSLCode" + #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas -Dnewt.debug.Window" #D_ARGS="-Djogl.debug.FBObject" #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" - #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" + #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Djogl.fbo.force.none" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all" @@ -208,7 +210,7 @@ function testawtswt() { } # -# newt (testnoawt and testawt) +# core/newt (testnoawt and testawt) # #testnoawt com.jogamp.nativewindow.NativeWindowVersion $* #testnoawt com.jogamp.opengl.JoglVersion $* @@ -237,6 +239,26 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* + +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $* + +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOffThreadSharedContextMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1DemoES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT + +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* + #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $* @@ -331,10 +353,8 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* #testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* -testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* +#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* -#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* -#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $* @@ -376,24 +396,6 @@ testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $* -# -# FBO / .. -# - -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable00NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable01NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable01bNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable02NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableMix2DemosES2NEWT $* -#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* -#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* - # # Graph # diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h index 47b51a509..c627f67de 100644 --- a/make/stub_includes/opengl/macosx-window-system.h +++ b/make/stub_includes/opengl/macosx-window-system.h @@ -13,6 +13,7 @@ #include #include #include +#include typedef int Bool; @@ -51,12 +52,13 @@ NSOpenGLPixelBuffer* createPBuffer(int renderTarget, int internalFormat, int wid Bool destroyPBuffer(NSOpenGLPixelBuffer* pBuffer); void setContextPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer); void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer, GLenum colorBuffer); +Bool isNSOpenGLPixelBuffer(uint64_t object); -// NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSView* view, Bool opaque); -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* pbuffer, Bool opaque, int texWidth, int texHeight); +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight); void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval); void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros); -void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* glLayer); +void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer); +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight); void releaseNSOpenGLLayer(NSOpenGLLayer *glLayer); void* getProcAddress(const char *procName); @@ -67,6 +69,3 @@ void setSwapInterval(NSOpenGLContext* ctx, int interval); Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRamp); void resetGammaRamp(); -/* returns the screen refresh rate in Hz */ -int getScreenRefreshRate(int scrn_idx); - diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 8a6495e6b..cc0af29a9 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -35,6 +35,7 @@ import javax.media.opengl.GL; import javax.media.opengl.GL2GL3; import javax.media.opengl.GL3; import javax.media.opengl.GLBase; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -61,55 +62,33 @@ public class FBObject { protected static final boolean DEBUG = Debug.debug("FBObject"); private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true); + private static enum DetachAction { NONE, DISPOSE, RECREATE }; + /** - * Returns true if basic FBO support is available, otherwise false. - *

- * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions - * ARB_ES2_compatibility, ARB_framebuffer_object, EXT_framebuffer_object or OES_framebuffer_object. - *

- *

- * Basic FBO support may only include one color attachment and no multisampling, - * as well as limited internal formats for renderbuffer. - *

- * @see GLContext#hasFBO() - */ - public static final boolean supportsBasicFBO(GL gl) { - return gl.getContext().hasFBO(); - } - - /** - * Returns true if full FBO support is available, otherwise false. - *

- * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions - * ARB_framebuffer_object, or all of - * EXT_framebuffer_object, EXT_framebuffer_multisample, - * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. - *

- *

- * Full FBO support includes multiple color attachments and multisampling. - *

+ * Marker interface, denotes a color buffer attachment. + *

Always an instance of {@link Attachment}.

+ *

Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. */ - public static final boolean supportsFullFBO(GL gl) { - return !forceMinimumFBOSupport && - ( gl.isGL3() || // GL >= 3.0 - gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object - - ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* - gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && - gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && - gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) - ) - ) ; - } - - public static final int getMaxSamples(GL gl) { - if( supportsFullFBO(gl) ) { - int[] val = new int[] { 0 } ; - gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); - return val[0]; - } else { - return 0; - } + public static interface Colorbuffer { + /** + * Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is zero. + * @return true if newly initialized, otherwise false. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public boolean initialize(GL gl) throws GLException; + + /** + * Releases the color buffer if initialized, i.e. name is not zero. + * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException; + + /** + * Writes the internal format to the given GLCapabilities object. + * @param caps the destination for format bits + * @param rgba8Avail whether rgba8 is available + */ + public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail); } /** Common super class of all attachments */ @@ -155,21 +134,89 @@ public class FBObject { private int name; - /** true if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */ - protected boolean resourceOwner; - - private int initCounter; - protected Attachment(Type type, int iFormat, int width, int height, int name) { this.type = type; this.format = iFormat; this.width = width; this.height = height; this.name = name; - this.resourceOwner = false; - this.initCounter = 0; } + /** + * Writes the internal format to the given GLCapabilities object. + * @param caps the destination for format bits + * @param rgba8Avail whether rgba8 is available + */ + public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) { + final int _format; + switch(format) { + case GL.GL_RGBA: + _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4; + break; + case GL.GL_RGB: + _format = rgba8Avail ? GL.GL_RGB8 : GL.GL_RGB565; + break; + default: + _format = format; + } + switch(_format) { + case GL.GL_RGBA4: + caps.setRedBits(4); + caps.setGreenBits(4); + caps.setBlueBits(4); + caps.setAlphaBits(4); + break; + case GL.GL_RGB5_A1: + caps.setRedBits(5); + caps.setGreenBits(5); + caps.setBlueBits(5); + caps.setAlphaBits(1); + break; + case GL.GL_RGB565: + caps.setRedBits(5); + caps.setGreenBits(6); + caps.setBlueBits(5); + caps.setAlphaBits(0); + break; + case GL.GL_RGB8: + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setAlphaBits(0); + break; + case GL.GL_RGBA8: + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setAlphaBits(8); + break; + case GL.GL_DEPTH_COMPONENT16: + caps.setDepthBits(16); + break; + case GL.GL_DEPTH_COMPONENT24: + caps.setDepthBits(24); + break; + case GL.GL_DEPTH_COMPONENT32: + caps.setDepthBits(32); + break; + case GL.GL_STENCIL_INDEX1: + caps.setStencilBits(1); + break; + case GL.GL_STENCIL_INDEX4: + caps.setStencilBits(4); + break; + case GL.GL_STENCIL_INDEX8: + caps.setStencilBits(8); + break; + case GL.GL_DEPTH24_STENCIL8: + caps.setDepthBits(24); + caps.setStencilBits(8); + break; + default: + throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format)); + } + } + /** width of attachment */ public final int getWidth() { return width; } /** height of attachment */ @@ -180,45 +227,31 @@ public class FBObject { public final int getName() { return name; } /* pp */ final void setName(int n) { name = n; } - public final int getInitCounter() { return initCounter; } - /** - * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero. - *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.

- * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. - */ - public void initialize(GL gl) throws GLException { - initCounter++; - /* - super.initialize(gl); - if(1 == getInitCounter() && 0 == getName() ) { + * Initializes the attachment and set it's parameter, if uninitialized, i.e. name is zero. + *
+            final boolean init = 0 == name;
+            if( init ) {
                 do init ..
-                freeResources = true; // if all OK
             }
-            */
-        }
+            return init;
+         * 
+ * @return true if newly initialized, otherwise false. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public abstract boolean initialize(GL gl) throws GLException; /** - * Releases the attachment buffer if initialized, i.e. name is zero. - *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.

- * @throws GLException if buffer release fails. - */ - public void free(GL gl) throws GLException { - /* - if(1 == getInitCounter() && freeResources && .. ) { + * Releases the attachment if initialized, i.e. name is not zero. + *
+            if(0 != name) {
                 do free ..
-            }
-            super.free(gl);
-            */
-            initCounter--;
-            if(0 == initCounter) {
-                resourceOwner = false;
                 name = 0;
             }
-            if(DEBUG) {
-                System.err.println("Attachment.free: "+this);
-            }
-        }
+         * 
+ * @throws GLException if buffer release fails. + */ + public abstract void free(GL gl) throws GLException; /** *

@@ -232,9 +265,9 @@ public class FBObject { if( ! ( o instanceof Attachment ) ) return false; final Attachment a = (Attachment)o; return type == a.type && - format == a.format || - width == a.width || - height== a.height || + format == a.format && + width == a.width && + height== a.height && name == a.name ; } @@ -259,8 +292,7 @@ public class FBObject { public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ - ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } public static Type getType(int attachmentPoint, int maxColorAttachments) { @@ -277,7 +309,7 @@ public class FBObject { } } } - + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ public static class RenderAttachment extends Attachment { private int samples; @@ -339,14 +371,13 @@ public class FBObject { } @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenRenderbuffers(1, name, 0); - if( 0 == name[0] ) { - throw new GLException("null renderbuffer, "+this); - } setName(name[0]); gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); @@ -355,43 +386,37 @@ public class FBObject { } else { gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteRenderbuffers(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; if(DEBUG) { System.err.println("Attachment.init: "+this); } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); } public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ - ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } } - /** - * Marker interface, denotes a color buffer attachment. - *

Always an instance of {@link Attachment}.

- *

Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. - */ - public static interface Colorbuffer { - } - /** Color render buffer attachment */ public static class ColorAttachment extends RenderAttachment implements Colorbuffer { public ColorAttachment(int iFormat, int samples, int width, int height, int name) { @@ -444,9 +469,11 @@ public class FBObject { * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. */ @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenTextures(1, name, 0); if(0 == name[0]) { @@ -468,31 +495,111 @@ public class FBObject { if( 0 < wrapT ) { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteTextures(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; - } - if(DEBUG) { - System.err.println("Attachment.init: "+this); + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteTextures(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); + } + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + *

Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

+ * + * @param glp the chosen {@link GLProfile} + * @param alpha set to true if you request alpha channel, otherwise false; + * @param width texture width + * @param height texture height + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) { + return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + * @param glp the chosen {@link GLProfile} + * @param alpha set to true if you request alpha channel, otherwise false; + * @param width texture width + * @param height texture height + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height, + int magFilter, int minFilter, int wrapS, int wrapT) { + final int textureInternalFormat, textureDataFormat, textureDataType; + if(glp.isGLES()) { + textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataType = GL.GL_UNSIGNED_BYTE; + } else { + textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; + textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; + textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; + } + return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}. + * + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param width texture width + * @param height texture height + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) { + return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */); + } + + private static boolean hasAlpha(int format) { + switch(format) { + case GL.GL_RGBA8: + case GL.GL_RGBA4: + case GL.GL_RGBA: + case GL.GL_BGRA: + case 4: + return true; + default: + return false; } } private boolean initialized; - private boolean basicFBOSupport; private boolean fullFBOSupport; private boolean rgba8Avail; private boolean depth24Avail; @@ -523,6 +630,9 @@ public class FBObject { // private final void validateColorAttachmentPointRange(int point) { + if(!initialized) { + throw new GLException("FBO not initialized"); + } if(maxColorAttachments != colorAttachmentPoints.length) { throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints); } @@ -621,7 +731,6 @@ public class FBObject { this.initialized = false; // TBD @ init - this.basicFBOSupport = false; this.fullFBOSupport = false; this.rgba8Avail = false; this.depth24Avail = false; @@ -657,14 +766,11 @@ public class FBObject { private void init(GL gl, int width, int height, int samples) throws GLException { if(initialized) { throw new GLException("FBO already initialized"); - } - fullFBOSupport = supportsFullFBO(gl); - - if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + } + if( !gl.hasBasicFBOSupport() ) { throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); } - - basicFBOSupport = true; + fullFBOSupport = gl.hasFullFBOSupport(); rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); @@ -680,10 +786,7 @@ public class FBObject { int val[] = new int[1]; - int glerr = gl.glGetError(); - if(DEBUG && GL.GL_NO_ERROR != glerr) { - System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); - } + int glerr = checkPreGLError(gl); int realMaxColorAttachments = 1; maxColorAttachments = 1; @@ -703,16 +806,7 @@ public class FBObject { colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; colorAttachmentCount = 0; - maxSamples = 0; - if(fullFBOSupport) { - gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); - glerr = gl.glGetError(); - if(GL.GL_NO_ERROR == glerr) { - maxSamples = val[0]; - } else if(DEBUG) { - System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); - } - } + maxSamples = gl.getMaxRenderbufferSamples(); if(!forceMinimumFBOSupport) { gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); maxTextureSize = val[0]; @@ -733,10 +827,9 @@ public class FBObject { this.samples = samples <= maxSamples ? samples : maxSamples; if(DEBUG) { - System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); - System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples"); System.err.println("fullFBOSupport: "+fullFBOSupport); - System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]"); System.err.println("maxSamples: "+maxSamples); System.err.println("maxTextureSize: "+maxTextureSize); System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); @@ -761,12 +854,8 @@ public class FBObject { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } - if(null != samplesSink) { - // init sampling sink - samplesSink.reset(gl, width, height); - resetMSAATexture2DSink(gl); - } - + resetMSAATexture2DSink(gl); + // generate fbo .. gl.glGenFramebuffers(1, val, 0); fbName = val[0]; @@ -780,7 +869,8 @@ public class FBObject { if(!gl.glIsFramebuffer(fbName)) { checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException } - bound = true; + bound = true; + samplesSinkDirty = true; initialized = true; updateStatus(gl); @@ -797,7 +887,7 @@ public class FBObject { * to match the new given parameters. *

*

- * Currently incompatibility and hence recreation is given if + * Incompatibility and hence recreation is forced if * the size or sample count doesn't match for subsequent calls. *

* @@ -820,17 +910,17 @@ public class FBObject { * to match the new given parameters. *

*

- * Currently incompatibility and hence recreation is given if - * the size or sample count doesn't match for subsequent calls. + * Currently incompatibility and hence recreation of the attachments will be performed + * if the size or sample count doesn't match for subsequent calls. *

* *

Leaves the FBO bound state untouched

* * @param gl the current GL context - * @param newWidth - * @param newHeight + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. - * @throws GLException in case of an error + * @throws GLException in case of an error, i.e. size too big, etc .. */ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { if(!initialized) { @@ -841,13 +931,15 @@ public class FBObject { newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp if( newWidth != width || newHeight != height || newSamples != samples ) { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } if(newWidth > 2 + maxTextureSize || newHeight> 2 + maxTextureSize || newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } if(DEBUG) { - System.err.println("FBObject.reset - START - "+this); + System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this); } final boolean wasBound = isBound(); @@ -856,11 +948,18 @@ public class FBObject { height = newHeight; samples = newSamples; detachAllImpl(gl, true , true); - resetMSAATexture2DSink(gl); - if(wasBound) { - bind(gl); - } else { + /** + * Postpone reset of samplesSink until syncFramebuffer, + * issued at use(..) method (swapBuffer usually initiates it). + * This allows another thread to still use the 'samplesSinkTexture' + * until swapBuffer happens and does not invalidate the GL_FRONT + * FBO (framebuffer & texture). + resetMSAATexture2DSink(gl); + */ + samplesSinkDirty = true; + + if(!wasBound) { unbind(gl); } @@ -870,6 +969,28 @@ public class FBObject { } } + /** + * Writes the internal format of the attachments to the given GLCapabilities object. + * @param caps the destination for format bits + */ + public final void formatToGLCapabilities(GLCapabilities caps) { + caps.setSampleBuffers(samples > 0); + caps.setNumSamples(samples); + caps.setDepthBits(0); + caps.setStencilBits(0); + + final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0); + if(null != cb) { + cb.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != depth) { + depth.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != stencil && stencil != depth) { + stencil.formatToGLCapabilities(caps, rgba8Avail); + } + } + /** * Note that the status may reflect an incomplete state during transition of attachments. * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 @@ -954,6 +1075,15 @@ public class FBObject { } } + private static int checkPreGLError(GL gl) { + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("Pre-existing GL error: 0x"+Integer.toHexString(glerr)); + Thread.dumpStack(); + } + return glerr; + } + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { if(GL.GL_NO_ERROR != err) { if(null != gl) { @@ -974,7 +1104,7 @@ public class FBObject { } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *

Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

@@ -986,13 +1116,15 @@ public class FBObject { * @param alpha set to true if you request alpha channel, otherwise false; * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException { - return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *

Leaves the FBO bound.

@@ -1006,23 +1138,15 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataType = GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; - textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; - textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; - } - return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point. * *

Leaves the FBO bound.

* @@ -1037,66 +1161,33 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(int, int, int, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, int internalFormat, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - return attachTexture2D(gl, attachmentPoint, - new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, - magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Creates a {@link ColorAttachment}, selecting the format automatically. * - *

- * In case the passed TextureAttachment texA is uninitialized, i.e. it's texture name is zero, - * a new texture name is generated and setup w/ the texture parameter.
- * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is - * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. - *

- * - *

Leaves the FBO bound.

- * - * @param gl the current GL context - * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. - * @return the passed TextureAttachment texA instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @param alpha set to true if you request alpha channel, otherwise false; + * @return uninitialized ColorAttachment instance describing the new attached colorbuffer */ - public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException { - validateAddColorAttachment(attachmentPoint, texA); - - if(samples>0) { - removeColorAttachment(attachmentPoint, texA); - throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); - } - - texA.initialize(gl); - addColorAttachment(attachmentPoint, texA); - - bind(gl); - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_TEXTURE_2D, texA.getName(), 0); - - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); - } - } - if(DEBUG) { - System.err.println("FBObject.attachTexture2D: "+this); + public final ColorAttachment createColorAttachment(boolean alpha) { + final int internalFormat; + if( rgba8Avail ) { + internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; + } else { + internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; } - return texA; + return new ColorAttachment(internalFormat, samples, width, height, 0); } - + /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point, * selecting the format automatically. * *

Leaves the FBO bound.

@@ -1106,19 +1197,14 @@ public class FBObject { * @param alpha set to true if you request alpha channel, otherwise false; * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the colorbuffer couldn't be allocated + * @see #createColorAttachment(boolean) */ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException { - final int internalFormat; - if( rgba8Avail ) { - internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; - } else { - internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; - } - return attachColorbuffer(gl, attachmentPoint, internalFormat); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point. * *

Leaves the FBO bound.

* @@ -1135,46 +1221,80 @@ public class FBObject { throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); } - return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, + * to this FBO's instance at the given attachment point. * + *

+ * If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is zero, + * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is + * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. + *

+ * *

Leaves the FBO bound.

* * @param gl * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param colA the template for the new {@link ColorAttachment} - * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the colorbuffer couldn't be allocated + * @param colbuf the to be attached {@link Colorbuffer} + * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment} */ - public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { - validateAddColorAttachment(attachmentPoint, colA); - - colA.initialize(gl); - addColorAttachment(attachmentPoint, colA); + public final Colorbuffer attachColorbuffer(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { + validateAddColorAttachment(attachmentPoint, colbuf); - bind(gl); + final boolean initializedColorbuf = colbuf.initialize(gl); + addColorAttachment(attachmentPoint, colbuf); - // Attach the color buffer - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_RENDERBUFFER, colA.getName()); + bind(gl); - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + if(initializedColorbuf) { + texA.free(gl); + } + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } } } if(DEBUG) { - System.err.println("FBObject.attachColorbuffer: "+this); + System.err.println("FBObject.attachColorbuffer: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this); } - return colA; + return colbuf; } - /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, @@ -1355,33 +1475,39 @@ public class FBObject { if(!ignoreStatus) { updateStatus(gl); if( !isStatusValid() ) { - detachRenderbuffer(gl, atype); + detachRenderbuffer(gl, atype, true); throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); } } if(DEBUG) { - System.err.println("FBObject.attachRenderbuffer: "+this); - } + System.err.println("FBObject.attachRenderbuffer: [attachmentType "+atype+"]: "+this); + } } /** + * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. *

Leaves the FBO bound!

+ * * @param gl - * @param ca + * @param attachmentPoint + * @param dispose true if the Colorbuffer shall be disposed + * @return the detached Colorbuffer * @throws IllegalArgumentException */ - public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { - if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException { + final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(null == res) { throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); } if(DEBUG) { - System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+"]: "+this); + System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this); } + return res; } - private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { - final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) { + Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here if(null == colbuf) { return null; @@ -1389,6 +1515,8 @@ public class FBObject { bind(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1397,11 +1525,22 @@ public class FBObject { GL.GL_TEXTURE_2D, 0, 0); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); } - texA.free(gl); - removeColorAttachment(attachmentPoint, texA); - if(recreate) { - texA.setSize(width, height); - attachTexture2D(gl, attachmentPoint, texA); + switch(detachAction) { + case DISPOSE: + texA.free(gl); + break; + case RECREATE: + texA.free(gl); + if(samples == 0) { + // stay non MSAA + texA.setSize(width, height); + } else { + // switch to MSAA + colbuf = createColorAttachment(hasAlpha(texA.format)); + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; @@ -1410,12 +1549,30 @@ public class FBObject { GL.GL_COLOR_ATTACHMENT0+attachmentPoint, GL.GL_RENDERBUFFER, 0); } - colA.free(gl); - removeColorAttachment(attachmentPoint, colbuf); - if(recreate) { - colA.setSize(width, height); - colA.setSamples(samples); - attachColorbuffer(gl, attachmentPoint, colA); + switch(detachAction) { + case DISPOSE: + colA.free(gl); + break; + case RECREATE: + colA.free(gl); + if(samples > 0) { + // stay MSAA + colA.setSize(width, height); + colA.setSamples(samples); + } else { + // switch to non MSAA + if(null != samplesSinkTexture) { + colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height, + samplesSinkTexture.dataFormat, samplesSinkTexture.dataType, + samplesSinkTexture.magFilter, samplesSinkTexture.minFilter, + samplesSinkTexture.wrapS, samplesSinkTexture.wrapT); + } else { + colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); + } + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } return colbuf; @@ -1424,10 +1581,14 @@ public class FBObject { /** * * @param gl + * @param dispose true if the Colorbuffer shall be disposed * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} */ - public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { - detachRenderbufferImpl(gl, atype, false); + public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(DEBUG) { + System.err.println("FBObject.detachRenderbuffer: [attachmentType "+atype+", dispose "+dispose+"]: "+this); + } } public final boolean isDepthStencilPackedFormat() { @@ -1439,7 +1600,7 @@ public class FBObject { return res; } - private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException { switch ( atype ) { case DEPTH: case STENCIL: @@ -1485,8 +1646,14 @@ public class FBObject { if( 0 != depth.getName() ) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; } break; @@ -1495,8 +1662,14 @@ public class FBObject { if(0 != stencil.getName()) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { stencil = null; } break; @@ -1506,9 +1679,15 @@ public class FBObject { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; stencil = null; } @@ -1516,14 +1695,15 @@ public class FBObject { default: throw new InternalError("XXX"); } - if(recreate) { + if(DetachAction.RECREATE == detachAction) { attachRenderbufferImpl2(gl, action, format); } } } /** - * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s. + * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s + * and disposes them. *

Leaves the FBO bound!

*

* An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1538,7 +1718,8 @@ public class FBObject { } /** - * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s + * and disposes them. *

Leaves the FBO bound!

*

* An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1553,7 +1734,7 @@ public class FBObject { } /** - * Detaches all {@link TextureAttachment}s + * Detaches all {@link TextureAttachment}s and disposes them. *

Leaves the FBO bound!

*

* An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1566,30 +1747,33 @@ public class FBObject { } for(int i=0; i reset try { for(int i=0; i0 ) { throw new InternalError("Non zero ColorAttachments "+this); } if(detachNonColorbuffer) { - detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate); + detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE); } if(ignoreStatus) { // post validate updateStatus(gl); @@ -1651,14 +1835,22 @@ public class FBObject { } private final void resetMSAATexture2DSink(GL gl) throws GLException { + if(null == samplesSink ) { + return; // this is the sample sink! + } if(0 == samples) { // MSAA off - if(null != samplesSink) { + if(samplesSink.initialized) { + // cleanup samplesSink.detachAll(gl); } return; } + if(!samplesSink.initialized) { + samplesSink.init(gl, width, height, 0); + } + boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch(); boolean sampleSinkTexMismatch = sampleSinkTexMismatch(); boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); @@ -1692,7 +1884,7 @@ public class FBObject { samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true); } else if( 0 == samplesSinkTexture.getName() ) { samplesSinkTexture.setSize(width, height); - samplesSink.attachTexture2D(gl, 0, samplesSinkTexture); + samplesSink.attachColorbuffer(gl, 0, samplesSinkTexture); } if( sampleSinkDepthStencilMismatch ) { @@ -1768,6 +1960,17 @@ public class FBObject { bound = false; } } + + /** + * Method simply marks this FBO unbound w/o interfering w/ the bound framebuffer as perfomed by {@link #unbind(GL)}. + *

+ * Only use this method if a subsequent {@link #unbind(GL)}, {@link #use(GL, TextureAttachment)} or {@link #bind(GL)} + * follows on any FBO. + *

+ */ + public final void markUnbound() { + bound = false; + } /** * Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. @@ -1785,49 +1988,54 @@ public class FBObject { public final boolean isBound() { return bound; } /** - * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}. - * - *

The operation is skipped, if no multisampling is used or - * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, - * see {@link #isSamplingBufferDirty()}

- * - *

If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing - * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

- * - *

In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization, + * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}. + *

+ * Method also updates the sampling sink configuration (if used). Hence it is recommended to call this + * method after your have initialized the FBO and attached renderbuffer etc for the 1st time. + * Method is called automatically by {@link #use(GL, TextureAttachment)}. + *

+ *

+ * Methos always resets the framebuffer binding to default in the end. + * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()} + *

+ *

+ * In case you use this FBO w/o the {@link GLFBODrawable} and intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); *

- * *

Leaves the FBO unbound.

* * @param gl the current GL context * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} * @throws IllegalArgumentException */ - public final void syncSamplingBuffer(GL gl) { - unbind(gl); + public final void syncFramebuffer(GL gl) { + markUnbound(); if(samples>0 && samplesSinkDirty) { samplesSinkDirty = false; resetMSAATexture2DSink(gl); gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName); gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer()); - ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2GL3 is OK GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); - if(fullFBOSupport) { - // default read/draw buffers, may utilize GLContext/GLDrawable override of - // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() - gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); - gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); - } else { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer - } + } + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer } } /** * Bind the given texture colorbuffer. * - *

If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.

+ *

If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first!

+ * + *

{@link #syncFramebuffer(GL)} is being called

* *

Leaves the FBO unbound!

* @@ -1837,11 +2045,7 @@ public class FBObject { */ public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { if(null == ta) { throw new IllegalArgumentException("null TextureAttachment, this: "+toString()); } - if(samples > 0 && samplesSinkTexture == ta) { - syncSamplingBuffer(gl); - } else { - unbind(gl); - } + syncFramebuffer(gl); gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. } @@ -1855,14 +2059,8 @@ public class FBObject { gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it } - /** - * Returns true if basic or full FBO is supported, otherwise false. - * @param full true for full FBO supported query, otherwise false for basic FBO support query. - * @see #supportsFullFBO(GL) - * @see #supportsBasicFBO(GL) - * @throws GLException if {@link #init(GL)} hasn't been called. - */ - public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; } + /** @see GL#hasFullFBOSupport() */ + public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; } /** * Returns true if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false. @@ -1878,7 +2076,7 @@ public class FBObject { public final boolean supportsDepth(int bits) throws GLException { checkInitialized(); switch(bits) { - case 16: return basicFBOSupport; + case 16: return true; case 24: return depth24Avail; case 32: return depth32Avail; default: return false; @@ -1913,11 +2111,11 @@ public class FBObject { */ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; } - /** - * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported. - * @throws GLException if {@link #init(GL)} hasn't been called. - */ - public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; } + public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; } + public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; } + + /** @see GL#getMaxRenderbufferSamples() */ + public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; } /** * Returns true if this instance has been initialized with {@link #reset(GL, int, int)} diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java new file mode 100644 index 000000000..38a8deef8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java @@ -0,0 +1,189 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +import jogamp.opengl.GLAutoDrawableBase; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; + + +/** + * Fully functional {@link GLAutoDrawable} implementation + * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. + *

+ * Since no native windowing system events are being processed, it is recommended + * to handle at least: + *

    + *
  • {@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #windowRepaintOp()}
  • + *
  • {@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #windowResizedOp()}
  • + *
  • {@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #windowDestroyNotifyOp()}
  • + *
+ *

+ *

+ * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. + *

+ */ +public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. + * @param lock optional custom {@link RecursiveLock}. + */ + public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice, RecursiveLock lock) { + super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); + if(null == drawable) { + throw new IllegalArgumentException("null drawable"); + } + if(null == context) { + throw new IllegalArgumentException("null context"); + } + if(!drawable.isRealized()) { + throw new IllegalArgumentException("drawable not realized"); + } + this.upstreamWidget = upstreamWidget; + this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ; + } + + // + // expose default methods + // + + /** Default implementation to handle repaint events from the windowing system */ + public final void windowRepaintOp() { + super.defaultWindowRepaintOp(); + } + + /** Implementation to handle resize events from the windowing system. All required locks are being claimed. */ + public final void windowResizedOp(int newWidth, int newHeight) { + super.defaultWindowResizedOp(newWidth, newHeight); + } + + /** + * Implementation to handle destroy notifications from the windowing system. + * + *

+ * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} + * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), + * a thread safe destruction is being induced. + *

+ */ + public final void windowDestroyNotifyOp() { + super.defaultWindowDestroyNotifyOp(); + } + + // + // Complete GLAutoDrawable + // + + private Object upstreamWidget; + private final RecursiveLock lock; + + @Override + protected final RecursiveLock getLock() { return lock; } + + @Override + public final Object getUpstreamWidget() { + return upstreamWidget; + } + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + public final void setUpstreamWidget(Object newUpstreamWidget) { + upstreamWidget = newUpstreamWidget; + } + + /** + * {@inheritDoc} + *

+ * This implementation calls {@link #defaultDestroy()}. + *

+ *

+ * User still needs to destroy the upstream window, which details are hidden from this aspect. + * This can be performed by overriding {@link #destroyImplInLock()}. + *

+ */ + @Override + public final void destroy() { + defaultDestroy(); + } + + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + } + + @Override + public void display() { + defaultDisplay(); + } + + // + // GLDrawable delegation + // + + @Override + public final GLDrawableFactory getFactory() { + return drawable.getFactory(); + } + + @Override + public final void setRealized(boolean realized) { + } + + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + ", \n\tUpstreamWidget: "+upstreamWidget+ /** ", \n\tFactory: "+factory+ */ "]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java index f7e25fa01..cf81b85ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -72,6 +72,9 @@ public class GLExtensions { public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; + public static final String ARB_shader_objects = "GL_ARB_shader_objects"; + // // Aliased GLX/WGL/.. extensions // diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java deleted file mode 100644 index 4caea03b2..000000000 --- a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.GLAutoDrawableDelegate; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLException; - -import jogamp.opengl.GLFBODrawableImpl; - -/** - * Platform-independent class exposing FBO offscreen functionality to - * applications. - *

- * This class distinguishes itself from {@link GLAutoDrawableDelegate} - * with it's {@link #setSize(int, int)} functionality. - *

- */ -public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. - */ - public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) { - super(drawable, context, null, ownDevice); - } - - /** - * Attempts to resize this offscreen auto drawable, if supported - * by the underlying {@link GLDrawable). - * @param newWidth - * @param newHeight - * @return true if resize was executed, otherwise false. - * @throws GLException in case of an error during the resize operation - */ - public boolean setSize(int newWidth, int newHeight) throws GLException { - boolean done = false; - if(drawable instanceof GLFBODrawableImpl) { - Throwable tFBO = null; - Throwable tGL = null; - context.makeCurrent(); - try { - ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight); - done = true; - } catch (Throwable t) { - tFBO = t; - } finally { - try { - context.release(); - } catch (Throwable t) { - tGL = t; - } - } - if(null != tFBO) { - throw new GLException("OffscreenAutoDrawable.setSize(..) GLFBODrawableImpl.setSize(..) exception", tFBO); - } - if(null != tGL) { - throw new GLException("OffscreenAutoDrawable.setSize(..) GLContext.release() exception", tGL); - } - } - if(done) { - this.defaultWindowResizedOp(); - return true; - } - return false; - } - - /** - * If the underlying {@link GLDrawable} is an FBO implementation - * and contains an {#link FBObject}, the same is returned. - * Otherwise returns null. - */ - public FBObject getFBObject() { - if(drawable instanceof GLFBODrawableImpl) { - return ((GLFBODrawableImpl)drawable).getFBObject(); - } - return null; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 8d237162c..02f62daec 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.swt; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; @@ -48,6 +49,7 @@ import javax.media.opengl.Threading; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; @@ -97,8 +99,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { private final GLCapabilitiesImmutable capsRequested; private final GLCapabilitiesChooser capsChooser; - private volatile GLDrawable drawable; // volatile: avoid locking for read-only access - private GLContext context; + private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access + private GLContextImpl context; /* Native window surface */ private AbstractGraphicsDevice device; @@ -319,7 +321,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { } }); } - private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { + private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() { @Override public final void create(ProxySurface s) { /* nop */ } @@ -349,7 +351,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) ) { clientArea = nClientArea; // write back new value - sendReshape = true; // Mark for OpenGL reshape next time the control is painted + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } + } } } @@ -391,10 +413,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { if(null != proxySurface) { /* Associate a GL surface with the proxy */ - drawable = glFactory.createGLDrawable(proxySurface); + drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface); drawable.setRealized(true); - context = drawable.createContext(shareWith); + context = (GLContextImpl) drawable.createContext(shareWith); } } finally { _lock.unlock(); @@ -455,6 +477,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { return helper.getAutoSwapBufferMode(); } + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public GLContext getContext() { return null != drawable ? context : null; @@ -502,7 +529,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { _lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 0b2c664fe..38f1746f9 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -114,6 +114,12 @@ public interface GLAutoDrawable extends GLDrawable { * where you drag the window to another monitor. */ public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true); + /** + * If the implementation uses delegation, return the delegated {@link GLDrawable} instance, + * otherwise return this instance. + */ + public GLDrawable getDelegatedDrawable(); + /** * Returns the context associated with this drawable. The returned * context will be synchronized. @@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable { /** * Associate a new context to this drawable and also propagates the context/drawable switch by * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}. - * drawable might be an inner GLDrawable instance if using such a delegation pattern, - * or this GLAutoDrawable itself. - *

- * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *

+ * drawable might be an inner GLDrawable instance if using a delegation pattern, + * or this GLAutoDrawable instance. *

* If the old or new context was current on this thread, it is being released before switching the drawable. * The new context will be made current afterwards, if it was current before. - * However the user shall take extra care that not other thread - * attempts to make this context current. Otherwise a race condition may happen. + * However the user shall take extra care that no other thread + * attempts to make this context current. + *

+ *

+ * Be aware that the old context is still bound to the drawable, + * and that one context can only be bound to one drawable at one time! *

*

- * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! + * In case you do not intend to use the old context anymore, i.e. + * not assigning it to another drawable, it shall be + * destroyed before setting the new context, i.e.: + *

+            GLContext oldCtx = glad.getContext();
+            if(null != oldCtx) {
+                oldCtx.destroy();
+            }
+            glad.setContext(newCtx);            
+   * 
+ * This is required, since a context must have a valid drawable at all times + * and this API shall not restrict the user in any way. *

* * @param newCtx the new context diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java deleted file mode 100644 index 67e81270d..000000000 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package javax.media.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -import jogamp.opengl.Debug; -import jogamp.opengl.GLAutoDrawableBase; -import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLDrawableImpl; - - -/** - * Fully functional {@link GLAutoDrawable} implementation - * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. - *

- * Since no native windowing system events are being processed, it is recommended - * to handle at least: - *

    - *
  • {@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #defaultWindowRepaintOp()}
  • - *
  • {@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #defaultWindowResizedOp()}
  • - *
  • {@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #defaultWindowDestroyNotifyOp()}
  • - *
- *

- *

- * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. - *

- */ -public class GLAutoDrawableDelegate extends GLAutoDrawableBase { - public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. - */ - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) { - super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); - this.upstreamWidget = null; - } - - // - // expose default methods - // - - public final void windowRepaintOp() { - super.defaultWindowRepaintOp(); - } - - public final void windowResizedOp() { - super.defaultWindowResizedOp(); - } - - public final void windowDestroyNotifyOp() { - super.defaultWindowDestroyNotifyOp(); - } - - // - // Complete GLAutoDrawable - // - - private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock - private final Object upstreamWidget; - - @Override - protected final RecursiveLock getLock() { return lock; } - - @Override - public final Object getUpstreamWidget() { - return upstreamWidget; - } - - /** - * {@inheritDoc} - *

- * This implementation calls {@link #defaultDestroy()}. - *

- *

- * User still needs to destroy the upstream window, which details are hidden from this aspect. - * This can be performed by overriding {@link #destroyImplInLock()}. - *

- */ - @Override - public final void destroy() { - defaultDestroy(); - } - - @Override - public void display() { - defaultDisplay(); - } - - // - // GLDrawable delegation - // - - @Override - public final GLDrawableFactory getFactory() { - return drawable.getFactory(); - } - - @Override - public final void setRealized(boolean realized) { - } - - @Override - public final void swapBuffers() throws GLException { - defaultSwapBuffers(); - } - -} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f5831a72d..9bcee819a 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -273,6 +273,42 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returns true if basic FBO support is available, otherwise false. + *

+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * GL_ARB_ES2_compatibility, GL_ARB_framebuffer_object, GL_EXT_framebuffer_object or GL_OES_framebuffer_object. + *

+ *

+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

+ * @see GLContext#hasBasicFBOSupport() + */ + public boolean hasBasicFBOSupport(); + + /** + * Returns true if full FBO support is available, otherwise false. + *

+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

+ *

+ * Full FBO support includes multiple color attachments and multisampling. + *

+ * @see GLContext#hasFullFBOSupport() + */ + public boolean hasFullFBOSupport(); + + /** + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. + * @see GLContext#getMaxRenderbufferSamples() + */ + public int getMaxRenderbufferSamples(); + /** * Returns true if the GL context supports non power of two (NPOT) textures, * otherwise false. @@ -284,6 +320,8 @@ public interface GLBase { */ public boolean isNPOTTextureAvailable(); + public boolean isTextureFormatBGRA8888Available(); + /** Provides a platform-independent way to specify the minimum swap interval for buffer swaps. An argument of 0 disables sync-to-vertical-refresh completely, while an argument of 1 diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index c2f94b9af..a5e639c74 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -96,6 +96,9 @@ public abstract class GLContext { */ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true); + protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true); + protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true); + public static final boolean DEBUG = Debug.debug("GLContext"); public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); @@ -127,9 +130,9 @@ public abstract class GLContext { /** GL_ARB_ES2_compatibility implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8; - /** Context supports basic FBO, details see {@link #hasFBO()}. + /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}. * Not a cache key. - * @see #hasFBO() + * @see #hasBasicFBOSupport() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) */ protected static final int CTX_IMPL_FBO = 1 << 9; @@ -178,11 +181,6 @@ public abstract class GLContext { * and made current afterwards. However the user shall take extra care that not other thread * attempts to make this context current. Otherwise a race condition may happen. *

- *

- * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! - *

* @param readWrite the read/write drawable for framebuffer operations. * @param setWriteOnly if true and if the current read-drawable differs * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}), @@ -603,12 +601,23 @@ public abstract class GLContext { /** * @return true if impl. is a hardware rasterizer, otherwise false. + * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile) * @see GLProfile#isHardwareRasterizer() */ public final boolean isHardwareRasterizer() { return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ; } + /** + * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} and major-version > 1. + * @see GLProfile#hasGLSL() + */ + public final boolean hasGLSL() { + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; + } + /** * Returns true if basic FBO support is available, otherwise false. *

@@ -620,21 +629,54 @@ public abstract class GLContext { * as well as limited internal formats for renderbuffer. *

* @see #CTX_IMPL_FBO - * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) - * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ - public final boolean hasFBO() { + public final boolean hasBasicFBOSupport() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; } + /** + * Returns true if full FBO support is available, otherwise false. + *

+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

+ *

+ * Full FBO support includes multiple color attachments and multisampling. + *

+ */ + public final boolean hasFullFBOSupport() { + return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() && + ( isGL3() || // GL >= 3.0 + isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) + ) + ) ; + } + /** - * @return true if context supports GLSL - * @see GLProfile#hasGLSL() + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. */ - public final boolean hasGLSL() { - return isGL2ES2() ; + public final int getMaxRenderbufferSamples() { + if( hasFullFBOSupport() ) { + final GL gl = getGL(); + final int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + return val[0]; + } else if(DEBUG) { + System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + return 0; } - + /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true. */ public boolean isNPOTTextureAvailable() { return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two); @@ -1014,6 +1056,9 @@ public abstract class GLContext { validateProfileBits(profile, "profile"); validateProfileBits(resCtp, "resCtp"); + if(FORCE_NO_FBO_SUPPORT) { + resCtp &= ~CTX_IMPL_FBO ; + } if(DEBUG) { System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null)); // Thread.dumpStack(); @@ -1197,17 +1242,35 @@ public abstract class GLContext { * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. *

*

- * FBO support is queried as described in {@link #hasFBO()}. + * FBO support is queried as described in {@link #hasBasicFBOSupport()}. *

* * @param device the device to request whether FBO is available for * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() + * @see GLContext#hasBasicFBOSupport() */ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); } + /** + * @return 1 if using a hardware rasterizer, 0 if using a software rasterizer and -1 if not determined yet. + * @see GLContext#isHardwareRasterizer() + * @see GLProfile#isHardwareRasterizer() + */ + public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) { + final int r; + final int ctp = getAvailableContextProperties(device, glp); + if(0 == ctp) { + r = -1; + } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) { + r = 1; + } else { + r = 0; + } + return r; + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 9fd895c1f..b6e7b0576 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -48,13 +48,16 @@ import java.util.List; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.opengl.GLAutoDrawableDelegate; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import jogamp.opengl.Debug; @@ -373,44 +376,63 @@ public abstract class GLDrawableFactory { // Methods to create high-level objects /** - * Returns a GLDrawable according to it's chosen Capabilities,
+ * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},
* which determines pixel format, on- and offscreen incl. PBuffer type. *

- * The native platform's chosen Capabilties are referenced within the target - * NativeSurface's AbstractGraphicsConfiguration.

- * - * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,
- * an onscreen GLDrawable will be realized. + * The chosen {@link GLCapabilitiesImmutable} are referenced within the target + * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.

+ *

*

- * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,
- * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,
- * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.
+ * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true. + *

*

- * + * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

+ *

+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

+ *

+ * If not onscreen and neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + *

+ * * @throws IllegalArgumentException if the passed target is null * @throws GLException if any window system-specific errors caused * the creation of the GLDrawable to fail. * + * @see #canCreateGLPbuffer(AbstractGraphicsDevice) + * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) + * @see javax.media.opengl.GLCapabilities#isOnscreen() + * @see javax.media.opengl.GLCapabilities#isFBO() + * @see javax.media.opengl.GLCapabilities#isPBuffer() * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ public abstract GLDrawable createGLDrawable(NativeSurface target) throws IllegalArgumentException, GLException; - + /** - * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *

- * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current. *

*

- * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true, + * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order. + *

+ *

+ * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. *

*

- * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. *

*

- * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated. *

* * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. @@ -418,17 +440,55 @@ public abstract class GLDrawableFactory { * @param chooser the custom chooser, may be null for default * @param width the requested offscreen width * @param height the requested offscreen height + * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance * - * @return the created offscreen GLDrawable + * @throws GLException if any window system-specific errors caused + * the creation of the Offscreen to fail. + * + * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) + */ + public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device, + GLCapabilitiesImmutable caps, + GLCapabilitiesChooser chooser, + int width, int height, + GLContext shareWith) throws GLException; + /** + * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + *

+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true, + * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order. + *

+ *

+ * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

+ *

+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

+ *

+ * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated. + *

+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. + * @param caps the requested GLCapabilties + * @param chooser the custom chooser, may be null for default + * @param width the requested offscreen width + * @param height the requested offscreen height + * + * @return the created offscreen {@link GLDrawable} * * @throws GLException if any window system-specific errors caused * the creation of the Offscreen to fail. + * + * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) */ public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device, - GLCapabilitiesImmutable capabilities, + GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, - int width, int height) - throws GLException; + int width, int height) throws GLException; /** * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. @@ -458,6 +518,21 @@ public abstract class GLDrawableFactory { long windowHandle, GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); + /** + * Returns true if it is possible to create an framebuffer object (FBO). + *

+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *

+ *

+ * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}. + *

+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasBasicFBOSupport() + */ + public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp); + /** * Returns true if it is possible to create a GLPbuffer. Some older * graphics cards do not have this capability. @@ -467,7 +542,10 @@ public abstract class GLDrawableFactory { public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); /** - * Creates a GLPbuffer with the given capabilites and dimensions.

+ * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions. + *

+ * The GLPbuffer drawable is realized and initialized eagerly. + *

* * See the note in the overview documentation on * context sharing. @@ -479,10 +557,12 @@ public abstract class GLDrawableFactory { * @param initialHeight initial height of pbuffer * @param shareWith a shared GLContext this GLPbuffer shall use * - * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable} + * @return the created and initialized {@link GLPbuffer} instance * * @throws GLException if any window system-specific errors caused * the creation of the GLPbuffer to fail. + * + * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)} */ public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java new file mode 100644 index 000000000..45fd3b686 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -0,0 +1,173 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Platform-independent {@link GLDrawable} specialization, + * exposing {@link FBObject} functionality. + * + *

+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound + * and made current the first time. + *

+ * + *

+ * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}. + *

+ *

+ * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}. + *

+ *

+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. + * Hence double buffering is always the case w/ MSAA. + *

+ *

+ * In non MSAA a second explicit {@link FBObject framebuffer} is being used. + * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection + * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}. + * This method also allows usage of both textures seperately. + *

+ *

+ * It would be possible to implement double buffering simply using + * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}. + * This would require mode selection and hence complicate the API. Besides, it would + * not support differentiation of read and write framebuffer and hence not be spec compliant. + *

+ *

+ * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer} + * is performed either in the {@link #contextMadeCurrent(boolean) context current hook} + * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
+ *

+ */ +public interface GLFBODrawable extends GLDrawable { + // public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * @return true if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise false. + */ + public boolean isInitialized(); + + /** + * Notify this instance about upstream size change + * to reconfigure the {@link FBObject}. + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @throws GLException if resize operation failed + */ + void resetSize(GL gl) throws GLException; + + /** + * @return the used texture unit + */ + int getTextureUnit(); + + /** + * + * @param unit the texture unit to be used + */ + void setTextureUnit(int unit); + + /** + * Set a new sample size + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @param newSamples new sample size + * @throws GLException if resetting the FBO failed + */ + void setNumSamples(GL gl, int newSamples) throws GLException; + + /** + * @return the number of sample buffers if using MSAA, otherwise 0 + */ + int getNumSamples(); + + /** + * @return the used {@link DoubleBufferMode} + */ + // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization}, + * otherwise an exception is thrown. + *

+ * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}. + * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested} + * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored. + *

+ *

+ * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect. + *

+ * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * If MSAA is being used and {@link GL#GL_FRONT} is requested, + * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. + * + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link FBObject} + * @throws IllegalArgumentException if an illegal buffer name is being used + */ + FBObject getFBObject(int bufferName) throws IllegalArgumentException; + + /** + * Returns the named texture buffer. + *

+ * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible + * and an exception is being thrown if {@link GL#GL_BACK} is being requested. + *

+ * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link TextureAttachment} + * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used + */ + FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException; + + /** Resizeable {@link GLFBODrawable} specialization */ + public interface Resizeable extends GLFBODrawable { + /** + * Resize this drawable. + *

+ * This drawable is being locked during operation. + *

+ * @param context the {@link GLContext} bound to this drawable, will be made current during operation + * A prev. current context will be make current after operation. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case an error during the resize operation occurred + */ + void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException; + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java new file mode 100644 index 000000000..6fe76a3f4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; + +/** + * Platform-independent {@link GLAutoDrawable} specialization, + * exposing offscreen functionality. + *

+ * This class distinguishes itself from {@link GLAutoDrawable} + * with it's {@link #setSize(int, int)} functionality. + *

+ */ +public interface GLOffscreenAutoDrawable extends GLAutoDrawable { + + /** + * Resize this auto drawable. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case of an error during the resize operation + */ + void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException; + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + void setUpstreamWidget(Object newUpstreamWidget); + + /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ + public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable { + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java index 273a992cf..de7731a3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -45,7 +45,11 @@ package javax.media.opengl; contains experimental methods for accessing the pbuffer's contents as a texture map and enabling rendering to floating-point frame buffers. These methods are not guaranteed to be supported on all - platforms and may be deprecated in a future release. */ + platforms and may be deprecated in a future release. + + @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} + via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}. + */ public interface GLPbuffer extends GLAutoDrawable { /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 033591fe3..329cf9e3f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper; interfaces when adding a heavyweight doesn't work either because of Z-ordering or LayoutManager problems. * + *
Offscreen Layer Remarks
+ * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + *

+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is false. + *

+ * *
Java2D OpenGL Remarks
* * To avoid any conflicts with a potential Java2D OpenGL context,
@@ -145,7 +156,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; - private volatile GLDrawable drawable; // volatile: avoid locking for read-only access + private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private GLContextImpl context; private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking @@ -237,6 +248,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // don't allow the user to change data capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable(); } + if(!capsReqUser.isOnscreen()) { + setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported + } if(null==device) { GraphicsConfiguration gc = super.getGraphicsConfiguration(); @@ -451,11 +465,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing /** Overridden to cause OpenGL rendering to be performed during repaint cycles. Subclasses which override this method must call super.paint() in their paint() method in order to function - properly.

- - Overrides: -

paint in class java.awt.Component
*/ - @Override + properly. + */ + @Override public void paint(Graphics g) { if (Beans.isDesignTime()) { // Make GLCanvas behave better in NetBeans GUI builder @@ -544,7 +556,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); jawtWindow.lockSurface(); try { - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); + drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); context = (GLContextImpl) drawable.createContext(shareWith); context.setContextCreationFlags(additionalCtxCreationFlags); } finally { @@ -561,13 +573,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if (!Beans.isDesignTime() && 0 < _drawable.getWidth() * _drawable.getHeight() ) { // make sure drawable realization happens on AWT EDT, due to AWTTree lock - AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction); - sendReshape=true; // ensure a reshape is being send .. - if(DEBUG) { - System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); - Thread.dumpStack(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction); + if( _drawable.isRealized() ) { + sendReshape=true; // ensure a reshape is being send .. + if(DEBUG) { + System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); + Thread.dumpStack(); + } + return true; } - return true; } } return false; @@ -575,7 +589,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private Runnable setRealizedOnEDTAction = new Runnable() { @Override public void run() { - drawable.setRealized(true); + final GLDrawable _drawable = drawable; + if ( null != _drawable && 0 < _drawable.getWidth() * _drawable.getHeight() ) { + _drawable.setRealized(true); + } } }; /**

Overridden to track when this component is removed from a @@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { - super.reshape(x, y, width, height); - final GLDrawable _drawable = drawable; - if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { - dispose(true); - } else { - sendReshape = true; + synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape + super.reshape(x, y, width, height); + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } } } - /** Overrides: -

update in class java.awt.Component
*/ /** * Overridden from Canvas to prevent the AWT's clearing of the * canvas from interfering with the OpenGL rendering. */ - @Override + @Override public void update(Graphics g) { paint(g); } @@ -681,7 +713,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing _lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -692,6 +724,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public GLContext getContext() { return context; @@ -866,7 +903,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(!disposeRegenerate) { if(null != awtConfig) { - disposeAbstractGraphicsDevice(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT); } awtConfig=null; } @@ -881,7 +918,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } }; - private final Runnable disposeAbstractGraphicsDeviceAction = new Runnable() { + /** + * Disposes the AbstractGraphicsDevice within EDT, + * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. + * + * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) + */ + private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() { @Override public void run() { if(null != awtConfig) { @@ -900,27 +943,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } }; - - /** - * Disposes the AbstractGraphicsDevice within EDT, - * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. - * - * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) - */ - private void disposeAbstractGraphicsDevice() { - if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { - disposeAbstractGraphicsDeviceAction.run(); - } else { - try { - EventQueue.invokeAndWait(disposeAbstractGraphicsDeviceAction); - } catch (InvocationTargetException e) { - throw new GLException(e.getTargetException()); - } catch (InterruptedException e) { - throw new GLException(e); - } - } - } - + private final Runnable initAction = new Runnable() { @Override public void run() { @@ -1046,7 +1069,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing * @param device * @return the chosen AWTGraphicsConfiguration * - * @see #disposeAbstractGraphicsDevice() + * @see #disposeAbstractGraphicsDeviceActionOnEDT */ private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index acb8f2183..6d4a5861f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -121,7 +121,7 @@ import com.jogamp.opengl.util.GLBuffers; *

*/ -@SuppressWarnings("serial") +@SuppressWarnings({ "serial", "deprecation" }) public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); @@ -396,7 +396,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing their reshape() method in order to function properly.

reshape in class java.awt.Component
*/ - @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); @@ -471,7 +470,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return null; } final GLContext oldCtx = backend.getContext(); - final boolean newCtxCurrent = helper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); backend.setContext(newCtx); if(newCtxCurrent) { newCtx.makeCurrent(); @@ -480,6 +479,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } + @Override + public final GLDrawable getDelegatedDrawable() { + if (backend == null) { + return null; + } + return backend.getDrawable(); + } + @Override public GLContext getContext() { if (backend == null) { diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index cc4e1b434..07029f143 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -30,16 +30,15 @@ package jogamp.opengl; import java.io.PrintStream; -import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; import javax.media.opengl.FPSCounter; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -49,6 +48,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; @@ -61,38 +61,36 @@ import com.jogamp.opengl.util.Animator; * @see GLWindow */ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { - public static final boolean DEBUG = Debug.debug("GLAutoDrawable"); + public static final boolean DEBUG = GLDrawableImpl.DEBUG; protected final GLDrawableHelper helper = new GLDrawableHelper(); protected final FPSCounterImpl fpsCounter = new FPSCounterImpl(); protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; - protected final boolean ownDevice; + protected final boolean ownsDevice; protected int additionalCtxCreationFlags = 0; protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking /** - * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet. - * @param context a valid {@link GLContextImpl}, may not be made current (created) yet. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. + * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization + * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization + * @param ownsDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. */ - public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) { + public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) { this.drawable = drawable; this.context = context; - this.ownDevice = ownDevice; + this.ownsDevice = ownsDevice; resetFPSCounter(); } + /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */ protected abstract RecursiveLock getLock(); - /** Returns the delegated GLDrawable */ - public final GLDrawable getDelegatedDrawable() { return drawable; } - /** Default implementation to handle repaint events from the windowing system */ protected final void defaultWindowRepaintOp() { final GLDrawable _drawable = drawable; @@ -103,29 +101,43 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } } - /** Default implementation to handle resize events from the windowing system */ - protected final void defaultWindowResizedOp() { - final GLDrawable _drawable = drawable; + /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */ + protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException { + GLDrawableImpl _drawable = drawable; if( null!=_drawable ) { if(DEBUG) { - System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = getLock(); + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight); + if(_drawable != _drawableNew) { + // write back + _drawable = _drawableNew; + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } } sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock if( _drawable.isRealized() ) { if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { display(); } - } + } } } - + /** * Default implementation to handle destroy notifications from the windowing system. * *

* If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), - * {@link #defaultDestroy()} is being called. + * a thread safe destruction is being induced. *

*/ protected final void defaultWindowDestroyNotifyOp() { @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { ctrl.resume(); } } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread + // Surface is locked by another thread. // Flag that destroy should be performed on the next // attempt to display. sendDestroy = true; // async, but avoiding deadlock @@ -225,7 +237,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } _drawable.setRealized(false); } - if( ownDevice ) { + if( ownsDevice ) { _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } } @@ -238,7 +250,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { _lock.lock(); try { if(drawable!=null && context != null) { - drawable.swapBuffers(); helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); } } finally { @@ -276,7 +287,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { destroy(); return; } - final RecursiveLock _lock = getLock(); + final RecursiveLock _lock = getLock(); _lock.lock(); try { if( null != context ) { @@ -294,6 +305,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { drawable.swapBuffers(); } } ; + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public final GLContext getContext() { return context; @@ -305,7 +321,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -529,4 +545,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getHandle() : 0; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]"; + } } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e82756022..050c619fd 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -47,6 +47,7 @@ import java.util.Map; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLNameResolver; @@ -85,6 +86,7 @@ public abstract class GLContextImpl extends GLContext { private String glRenderer; private String glRendererLowerCase; + private String glVersion; // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations @@ -126,6 +128,9 @@ public abstract class GLContextImpl extends GLContext { GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this); this.drawable = drawable; + if(null != drawable) { + drawable.associateContext(this, true); + } this.drawableRead = drawable; this.glDebugHandler = new GLDebugMessageHandler(this); @@ -205,8 +210,10 @@ public abstract class GLContextImpl extends GLContext { if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable drawableRead = (GLDrawableImpl) readWrite; } - final GLDrawable old = drawable; + final GLDrawableImpl old = drawable; + old.associateContext(this, false); drawable = (GLDrawableImpl) readWrite ; + drawable.associateContext(this, true); if(lockHeld) { makeCurrent(); } @@ -272,7 +279,7 @@ public abstract class GLContextImpl extends GLContext { if( actualRelease ) { if( !inDestruction ) { try { - drawable.contextMadeCurrent(this, false); + contextMadeCurrent(false); } catch (Throwable t) { drawableContextMadeCurrentException = t; } @@ -331,7 +338,8 @@ public abstract class GLContextImpl extends GLContext { makeCurrent(); } try { - drawable.contextRealized(this, false); + contextRealized(false); + drawable.associateContext(this, false); } catch (Throwable t) { drawableContextRealizedException = t; } @@ -514,19 +522,17 @@ public abstract class GLContextImpl extends GLContext { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } - drawable.contextRealized(this, true); + contextRealized(true); if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock); } - } else { - drawable.contextMadeCurrent(this, true); - - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); - } + } else if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); } + contextMadeCurrent(true); + /* FIXME: refactor dependence on Java 2D / JOGL bridge // Try cleaning up any stale server-side OpenGL objects @@ -608,6 +614,20 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void makeCurrentImpl() throws GLException; + /** + * @see GLDrawableImpl#contextRealized(GLContext, boolean) + */ + protected void contextRealized(boolean realized) { + drawable.contextRealized(this, realized); + } + + /** + * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) + */ + protected void contextMadeCurrent(boolean current) { + drawable.contextMadeCurrent(this, current); + } + /** * Platform dependent entry point for context creation.
* @@ -934,52 +954,43 @@ public abstract class GLContextImpl extends GLContext { /** * If major > 0 || minor > 0 : Use passed values, determined at creation time - * If major==0 && minor == 0 : Use GL_VERSION * Otherwise .. don't touch .. */ private final void setContextVersion(int major, int minor, int ctp, boolean setVersionString) { - if (0==ctp) { + if ( 0 == ctp ) { throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } - if(major>0 || minor>0) { - if (!GLContext.isValidGLVersion(major, minor)) { - GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); - throw e; - } - ctxMajorVersion = major; - ctxMinorVersion = minor; - ctxOptions = ctp; - if(setVersionString) { - ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); - } - return; + + if (!GLContext.isValidGLVersion(major, minor)) { + throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } - - if(major==0 && minor==0) { - String versionStr = getGL().glGetString(GL.GL_VERSION); - if(null==versionStr) { - throw new GLException("GL_VERSION is NULL: "+this); - } - ctxOptions = ctp; - - // Set version - GLVersionNumber version = new GLVersionNumber(versionStr); + ctxMajorVersion = major; + ctxMinorVersion = minor; + ctxOptions = ctp; + if(setVersionString) { + ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); + } + } + + private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) { + if( null != glVersionStr ) { + final GLVersionNumber version = new GLVersionNumber(glVersionStr); if (version.isValid()) { - ctxMajorVersion = version.getMajor(); - ctxMinorVersion = version.getMinor(); - // We cannot promote a non ARB context to >= 3.1, - // reduce it to 3.0 then. - if ( ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) - && 0 == (ctxOptions & CTX_IS_ARB_CREATED) ) { - ctxMajorVersion = 3; - ctxMinorVersion = 0; - } - if(setVersionString) { - ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); - } - return; + int major = version.getMajor(); + int minor = version.getMinor(); + // We cannot promote a non ARB context to >= 3.1, + // reduce it to 3.0 then. + if ( 0 == (ctp & CTX_IS_ARB_CREATED) && + ( major > 3 || major == 3 && minor >= 1 ) ) { + major = 3; + minor = 0; + } + if ( GLContext.isValidGLVersion(major, minor) ) { + return new VersionNumber(major, minor, 0); + } } } + return null; } //---------------------------------------------------------------------- @@ -1019,14 +1030,18 @@ public abstract class GLContextImpl extends GLContext { /** * Pbuffer support; given that this is a GLContext associated with a * pbuffer, binds this pbuffer to its texture target. + * @throws GLException if not implemented (default) + * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer */ - public abstract void bindPbufferToTexture(); + public void bindPbufferToTexture() { throw new GLException("not implemented"); } /** * Pbuffer support; given that this is a GLContext associated with a * pbuffer, releases this pbuffer from its texture target. + * @throws GLException if not implemented (default) + * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer */ - public abstract void releasePbufferFromTexture(); + public void releasePbufferFromTexture() { throw new GLException("not implemented"); } public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3); @@ -1064,7 +1079,7 @@ public abstract class GLContextImpl extends GLContext { table.reset(getDrawableImpl().getGLDynamicLookupHelper() ); } - private final boolean initGLRendererStrings() { + private final boolean initGLRendererAndGLVersionStrings() { final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString"); if(0 == _glGetString) { @@ -1083,14 +1098,27 @@ public abstract class GLContextImpl extends GLContext { Thread.dumpStack(); } return false; - } else { - glRenderer = _glRenderer; - glRendererLowerCase = glRenderer.toLowerCase(); - return true; } + glRenderer = _glRenderer; + glRendererLowerCase = glRenderer.toLowerCase(); + + final String _glVersion = glGetStringInt(GL.GL_VERSION, _glGetString); + if(null == _glVersion) { + // FIXME + if(DEBUG) { + System.err.println("Warning: GL_VERSION is NULL."); + Thread.dumpStack(); + } + return false; + } + glVersion = _glVersion; + return true; } } + protected final String getGLVersionString() { + return glVersion; + } protected final String getGLRendererString(boolean lowerCase) { return lowerCase ? glRendererLowerCase : glRenderer; } @@ -1128,17 +1156,44 @@ public abstract class GLContextImpl extends GLContext { final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); - if( !initGLRendererStrings() && DEBUG) { - System.err.println("Warning: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + { + final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(); + if(DEBUG) { + if( !initGLRendererAndGLVersionStringsOK ) { + System.err.println("Warning: setGLFunctionAvailability: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } else { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)); + } + } } if(!isCurrentContextHardwareRasterizer()) { ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT; } - + + // Pick the version from the GL-version string, + // if smaller _or_ given major == 0. + final VersionNumber glVersionNumber; + { + final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0); + final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion); + if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) { + glVersionNumber = strGLVersionNumber; + major = glVersionNumber.getMajor(); + minor = glVersionNumber.getMinor(); + } else { + glVersionNumber = setGLVersionNumber; + } + } + if ( !GLContext.isValidGLVersion(major, minor) ) { + throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+glVersionNumber); + } + if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2 + ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT; + } contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits); if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion) + ", "+glVersionNumber); } // @@ -1201,6 +1256,10 @@ public abstract class GLContextImpl extends GLContext { ctxProfileBits |= CTX_IMPL_FBO; } + if(FORCE_NO_FBO_SUPPORT) { + ctxProfileBits &= ~CTX_IMPL_FBO ; + } + // // Set GL Version (complete w/ version string) // diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index e1e253d35..4f965f620 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -48,18 +48,21 @@ import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.MutableSurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; -import javax.media.opengl.GLCapabilities; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; +import javax.media.opengl.GLFBODrawable; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize; +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; /** Extends GLDrawableFactory with a few methods for handling @@ -67,6 +70,7 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration; Independent Bitmaps on Windows, pixmaps on X11). Direct access to these GLDrawables is not supplied directly to end users, though they may be instantiated by the GLJPanel implementation. */ +@SuppressWarnings("deprecation") public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected static final boolean DEBUG = GLDrawableImpl.DEBUG; @@ -141,55 +145,53 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols) { // layered surface -> Offscreen/[FBO|PBuffer] - final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); - chosenCapsMod.setOnscreen(false); - chosenCapsMod.setDoubleBuffered(false); - /* if( isFBOAvailable ) { // FIXME JAU: FBO n/a yet - chosenCapsMod.setFBO(true); - } else */ - if( canCreateGLPbuffer(adevice) ) { - chosenCapsMod.setPBuffer(true); - } else { - chosenCapsMod.setFBO(false); - chosenCapsMod.setPBuffer(false); + final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ; + if(!isPbufferAvailable && !isFBOAvailable) { + throw new GLException("Neither FBO nor Pbuffer is available for "+target); } + final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable); config.setChosenCapabilities(chosenCapsMod); + ols.setChosenCapabilities(chosenCapsMod); if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer"); + System.err.println("chosenCaps: "+chosenCaps); + System.err.println("chosenCapsMod: "+chosenCapsMod); + System.err.println("OffscreenLayerSurface: **** "+ols); + System.err.println("Target: **** "+target); + Thread.dumpStack(); } if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); } - if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) { - // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. - final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); - result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + if( chosenCapsMod.isFBO() && isFBOAvailable ) { + // target surface is already a native one + result = createFBODrawableImpl(target, chosenCapsMod, 0); } else { result = createOffscreenDrawableImpl(target); } } else if(chosenCaps.isOnscreen()) { // onscreen + final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + config.setChosenCapabilities(chosenCapsMod); if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target); } result = createOnscreenDrawableImpl(target); } else { // offscreen - final GLCapabilitiesImmutable reqCaps = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO req / chosen - avail, PBuffer: "+reqCaps.isFBO()+" / "+chosenCaps.isFBO()+" - "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO chosen / avail, PBuffer: "+ + chosenCaps.isFBO()+" / "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target); } if( ! ( target instanceof MutableSurface ) ) { - throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target); + throw new IllegalArgumentException("Passed NativeSurface must implement MutableSurface for offscreen: "+target); } - if( reqCaps.isFBO() && isFBOAvailable ) { - // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. - final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); - result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + if( chosenCaps.isFBO() && isFBOAvailable ) { + // need to hook-up a native dummy surface since source may not have + final ProxySurface dummySurface = createDummySurfaceImpl(adevice, true, chosenCaps, null, 64, 64); + dummySurface.setUpstreamSurfaceHook(new DelegatedUpstreamSurfaceHookWithSurfaceSize(dummySurface.getUpstreamSurfaceHook(), target)); + result = createFBODrawableImpl(dummySurface, chosenCaps, 0); } else { - final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); - chosenCapsMod.setDoubleBuffered(false); - config.setChosenCapabilities(chosenCapsMod); result = createOffscreenDrawableImpl(target); } } @@ -211,7 +213,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // PBuffer Offscreen GLDrawable construction + // PBuffer Offscreen GLAutoDrawable construction // @Override @@ -239,7 +241,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLDrawableImpl drawable = null; device.lock(); try { - drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); + drawable = createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, + new UpstreamSurfaceHookMutableSize(width, height) ) ); if(null != drawable) { drawable.setRealized(true); } @@ -247,10 +250,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { device.unlock(); } - if(null==drawable) { - throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height); - } - return new GLPbufferImpl( drawable, shareWith, true); + return new GLPbufferImpl( drawable, (GLContextImpl) drawable.createContext(shareWith) ); } //--------------------------------------------------------------------------- @@ -258,6 +258,29 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // Offscreen GLDrawable construction // + public final boolean canCreateFBO(AbstractGraphicsDevice deviceReq, GLProfile glp) { + AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + if(null == device) { + throw new GLException("No shared device for requested: "+deviceReq); + } + return GLContext.isFBOAvailable(device, glp); + } + + @Override + public GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice deviceReq, + GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, + int width, int height, + GLContext shareWith) { + final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height ); + drawable.setRealized(true); + final GLContext context = drawable.createContext(shareWith); + if(drawable instanceof GLFBODrawableImpl) { + return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, context, null, null ); + } + return new GLOffscreenAutoDrawableImpl( drawable, context, null, null); + } + @Override public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, @@ -274,10 +297,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, GLContext.isFBOAvailable(device, capsRequested.getGLProfile()), canCreateGLPbuffer(device)); + if( capsChosen.isFBO() ) { device.lock(); try { - return createFBODrawableImpl(device, capsRequested, chooser, width, height); + final ProxySurface dummySurface = createDummySurfaceImpl(device, true, capsRequested, null, width, height); + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); + return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0); } finally { device.unlock(); } @@ -285,20 +311,17 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { device.lock(); try { - return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); + return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, + new UpstreamSurfaceHookMutableSize(width, height) ) ); } finally { device.unlock(); } } - /** Creates a platform independent offscreen FBO GLDrawable implementation */ - protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, - int initialWidth, int initialHeight) { - final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); - final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64); + /** Creates a platform independent FBO offscreen GLDrawable */ + protected GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) { final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); - - return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */); + return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit); } /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */ @@ -318,15 +341,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * @param capsChosen * @param capsRequested * @param chooser the custom chooser, may be null for default - * @param width the initial width - * @param height the initial height - * @param lifecycleHook optional control of the surface's lifecycle + * @param upstreamHook surface size information and optional control of the surface's lifecycle * @return the created {@link MutableSurface} instance w/o defined surface handle */ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook); + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook); /** * A dummy surface is not visible on screen and will not be used to render directly to, @@ -341,9 +362,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * @param width the initial width * @param height the initial height * - * @return the created {@link MutableSurface} instance w/o defined surface handle + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. */ - public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + public ProxySurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { @@ -369,9 +390,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * otherwise device instance is used as-is. * @param requestedCaps * @param chooser the custom chooser, may be null for default - * @param width the initial width - * @param height the initial height - * @return the created {@link MutableSurface} instance w/o defined surface handle + * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height, + * The latter is platform specific and small + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. */ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 090c5fe69..bdf0b6d74 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -43,12 +43,19 @@ package jogamp.opengl; import java.util.ArrayList; import java.util.HashSet; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; +import javax.media.opengl.GLFBODrawable; import javax.media.opengl.GLRunnable; import com.jogamp.opengl.util.Animator; @@ -108,24 +115,27 @@ public class GLDrawableHelper { /** * Associate a new context to the drawable and also propagates the context/drawable switch by * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}. - *

- * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *

*

* If the old or new context was current on this thread, it is being released before switching the drawable. *

+ *

+ * Be aware that the old context is still bound to the drawable, + * and that one context can only bound to one drawable at one time! + *

+ *

+ * No locking is being performed on the drawable, caller is required to take care of it. + *

* * @param drawable the drawable which context is changed - * @param newCtx the new context * @param oldCtx the old context - * @return true if the newt context was current, otherwise false + * @param newCtx the new context + * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)} + * @return true if the new context was current, otherwise false * * @see GLAutoDrawable#setContext(GLContext) */ - public final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int additionalCtxCreationFlags) { - if(null != oldCtx && oldCtx.isCurrent()) { + public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) { + if( null != oldCtx && oldCtx.isCurrent() ) { oldCtx.release(); } final boolean newCtxCurrent; @@ -134,17 +144,135 @@ public class GLDrawableHelper { if(newCtxCurrent) { newCtx.release(); } - newCtx.setContextCreationFlags(additionalCtxCreationFlags); + newCtx.setContextCreationFlags(newCtxCreationFlags); newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch } else { newCtxCurrent = false; } - if(null!=oldCtx && oldCtx.getGLDrawable() instanceof GLAutoDrawable) { - ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null); - } return newCtxCurrent; } + /** + * If the drawable is not realized, OP is a NOP. + *
    + *
  • release context if current
  • + *
  • destroy old drawable
  • + *
  • create new drawable
  • + *
  • attach new drawable to context
  • + *
  • make context current, if it was current
  • + *
+ *

+ * No locking is being performed, caller is required to take care of it. + *

+ * + * @param drawable + * @param context maybe null + * @return the new drawable + */ + public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, GLContext context) { + if( ! drawable.isRealized() ) { + return drawable; + } + final boolean contextCurrent = null != context && context.isCurrent(); + final GLDrawableFactory factory = drawable.getFactory(); + final NativeSurface surface = drawable.getNativeSurface(); + final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null; + + if(contextCurrent) { + context.release(); + } + + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(false); + } + try { + drawable.setRealized(false); + drawable = (GLDrawableImpl) factory.createGLDrawable(surface); // [2] + drawable.setRealized(true); + } finally { + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(true); + } + } + + if(null != context) { + context.setGLDrawable(drawable, true); // re-association + } + + if(contextCurrent) { + context.makeCurrent(); + } + return drawable; + } + + /** + * Performs resize operation on the given drawable, assuming it is offscreen. + *

+ * The {@link GLDrawableImpl}'s {@link NativeSurface} is being locked during operation. + * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller. + *

+ *

+ * May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)} + * in case of a a pbuffer- or pixmap-drawable. + *

+ *

+ * FBO drawables are resized w/o drawable destruction. + *

+ *

+ * Offscreen resize operation is validated w/ drawable size in the end. + * An exception is thrown if not successful. + *

+ * + * @param drawable + * @param context + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 + * @return the new drawable in case of an pbuffer/pixmap drawable, otherwise the passed drawable is being returned. + * @throws NativeWindowException is drawable is not offscreen or it's surface lock couldn't be claimed + * @throws GLException may be thrown a resize operation + */ + public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, GLContext context, int newWidth, int newHeight) + throws NativeWindowException, GLException + { + if(drawable.getChosenGLCapabilities().isOnscreen()) { + throw new NativeWindowException("Drawable is not offscreen: "+drawable); + } + final NativeSurface ns = drawable.getNativeSurface(); + final int lockRes = ns.lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface of drawable: "+drawable); + } + try { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } + // propagate new size + if(ns instanceof ProxySurface) { + final ProxySurface ps = (ProxySurface) ns; + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else if(DEBUG) { // we have to assume UpstreamSurfaceHook contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen ProxySurface n.a. UpstreamSurfaceHook.MutableSize, but "+ush.getClass().getName()+": "+ush); + } + } else if(DEBUG) { // we have to assume surface contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen surface n.a. ProxySurface, but "+ns.getClass().getName()+": "+ns); + } + if(drawable instanceof GLFBODrawable) { + if( null != context && context.isCreated() ) { + ((GLFBODrawable) drawable).resetSize(context.getGL()); + } + } else { + drawable = GLDrawableHelper.recreateGLDrawable(drawable, context); + } + } finally { + ns.unlockSurface(); + } + if(drawable.getWidth() != newWidth || drawable.getHeight() != newHeight) { + throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable); + } + return drawable; + } + public final void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } @@ -196,15 +324,11 @@ public class GLDrawableHelper { } } - private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { - if(listenersToBeInit.remove(l)) { - l.init(drawable); - if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); - } - return true; + private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { + l.init(drawable); + if(sendReshape) { + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); } - return false; } /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */ @@ -214,14 +338,11 @@ public class GLDrawableHelper { for (int i=0; i < _listeners.size(); i++) { final GLEventListener listener = _listeners.get(i) ; - // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. + // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), - // hence the must always be initialized unconditional. - listenersToBeInit.add(listener); - - if ( ! init( listener, drawable, true /* sendReshape */) ) { - throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); - } + // hence it must be called unconditional, always. + listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init + init( listener, drawable, true /* sendReshape */); } } } @@ -239,7 +360,9 @@ public class GLDrawableHelper { final GLEventListener listener = _listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable - init( listener, drawable, true /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, true /* sendReshape */) ; + } listener.display(drawable); } } @@ -251,7 +374,9 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable synchronized(listenersLock) { - init( listener, drawable, false /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, false /* sendReshape */) ; + } } } if(setViewport) { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index abf2bf557..311690f1d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -43,6 +43,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -76,31 +77,46 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] - if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { - return; + int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { + return; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + updateHandle(); + } + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } - swapBuffersImpl(); - } finally { - unlockSurface(); + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); } + swapBuffersImpl(false); } - } else { - GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFinish(); - } - } + } finally { + unlockSurface(); + } surface.surfaceUpdated(this, surface, System.currentTimeMillis()); } - protected abstract void swapBuffersImpl(); + + /** + * Platform and implementation depending surface swap. + *

The surface is locked.

+ *

+ * If doubleBuffered is true, + * an actual platform dependent surface swap shall be executed. + *

+ *

+ * If doubleBuffered is false, + * {@link GL#glFlush()} has been called already and + * the implementation may execute implementation specific code. + *

+ */ + protected abstract void swapBuffersImpl(boolean doubleBuffered); public final static String toHexString(long hex) { return "0x" + Long.toHexString(hex); @@ -181,6 +197,9 @@ public abstract class GLDrawableImpl implements GLDrawable { System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg); } } + /** + * Platform specific realization of drawable + */ protected abstract void setRealizedImpl(); /** @@ -189,7 +208,7 @@ public abstract class GLDrawableImpl implements GLDrawable { * If realized is true, the context has just been created and made current. *

*

- * If realized is false, the context is still current and will be release and destroyed after this method returns. + * If realized is false, the context is still current and will be released and destroyed after this method returns. *

*

* @see #contextMadeCurrent(GLContext, boolean) @@ -199,18 +218,27 @@ public abstract class GLDrawableImpl implements GLDrawable { /** * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent, release. *

- * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. - *

- *

* If current is true, the context has just been made current. *

*

* If current is false, the context is still current and will be release after this method returns. *

+ *

+ * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)} + * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}. + *

* @see #contextRealized(GLContext, boolean) */ protected void contextMadeCurrent(GLContext glc, boolean current) { } + /** + * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) + * or to remove such association (bound == false). + * @param ctx the just bounded or unbounded context + * @param bound if true create an association, otherwise remove it + */ + protected void associateContext(GLContext ctx, boolean bound) { } + /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/ protected int getDefaultDrawFramebuffer() { return 0; } /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */ @@ -245,8 +273,8 @@ public abstract class GLDrawableImpl implements GLDrawable { public String toString() { return getClass().getSimpleName()+"[Realized "+isRealized()+ ",\n\tFactory "+getFactory()+ - ",\n\thandle "+toHexString(getHandle())+ - ",\n\tWindow "+getNativeSurface()+"]"; + ",\n\tHandle "+toHexString(getHandle())+ + ",\n\tSurface "+getNativeSurface()+"]"; } protected static String getThreadName() { diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 03bc26cbc..de45466f3 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -1,142 +1,476 @@ package jogamp.opengl; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; -import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import javax.media.opengl.GLFBODrawable; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.Colorbuffer; import com.jogamp.opengl.FBObject.TextureAttachment; /** - * Offscreen GLDrawable implementation using framebuffer object (FBO) - * as it's offscreen rendering mechanism. + * {@link FBObject} offscreen GLDrawable implementation, i.e. {@link GLFBODrawable}. + *

+ * It utilizes the context lifecycle hook {@link #contextRealized(GLContext, boolean)} + * to initialize the {@link FBObject} instance. + *

+ *

+ * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)} + * to {@link FBObject#bind(GL) bind} the FBO. + *

+ * See {@link GLFBODrawable} for double buffering details. * * @see GLDrawableImpl#contextRealized(GLContext, boolean) * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) * @see GLDrawableImpl#getDefaultDrawFramebuffer() * @see GLDrawableImpl#getDefaultReadFramebuffer() */ -public class GLFBODrawableImpl extends GLDrawableImpl { - final GLDrawableImpl parent; - final FBObject fbo; - int texUnit; - int samplesTexUnit = 0; - int width=0, height=0, samples=0; - - protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, - NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) { +public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject"); + + private final GLDrawableImpl parent; + + private boolean initialized; + private int texUnit; + private int samples; + + private FBObject[] fbos; + private int fboIBack; // points to GL_BACK buffer + private int fboIFront; // points to GL_FRONT buffer + private FBObject pendingFBOReset = null; + private boolean fboBound; + private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure! + + // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + private SwapBufferContext swapBufferContext; + + public static interface SwapBufferContext { + public void swapBuffers(boolean doubleBuffered); + } + + protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { super(factory, surface, false); + this.initialized = false; + + // Replace the chosen caps of dummy-surface w/ it's clone and copied values of orig FBO caps request. + // The dummy-surface has already been configured, hence value replace is OK + // and due to cloning, the native GLCapability portion is being preserved. + final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilities fboCapsNative = (GLCapabilities) msConfig.getChosenCapabilities().cloneMutable(); + fboCapsNative.copyFrom(fboCaps); + msConfig.setChosenCapabilities(fboCapsNative); + this.parent = parent; this.texUnit = textureUnit; - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - this.width = initialWidth; - this.height = initialHeight; - this.samples = caps.getNumSamples(); - this.fbo = new FBObject(); + this.samples = fboCaps.getNumSamples(); + + // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ; + + this.swapBufferContext = null; } - @Override - protected void contextRealized(GLContext glc, boolean realized) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - final GL gl = glc.getGL(); - if(realized) { - fbo.reset(gl, width, height, samples); - samples = fbo.getNumSamples(); // update, maybe capped + private final void initialize(boolean realize, GL gl) { + if(realize) { + final int maxSamples = gl.getMaxRenderbufferSamples(); + samples = samples <= maxSamples ? samples : maxSamples; + + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + final int fbosN; if(samples > 0) { - fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; + } else if( caps.getDoubleBuffered() ) { + fbosN = bufferCount; } else { - fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; } - if( caps.getStencilBits() > 0 ) { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); - } else { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + + fbos = new FBObject[fbosN]; + fboIBack = 0; // head + fboIFront = fbos.length - 1; // tail + + for(int i=0; i 0) { + fbos[i].attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + } else { + fbos[i].attachTexture2D(gl, 0, caps.getAlphaBits()>0); + } + if( caps.getStencilBits() > 0 ) { + fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); + } else { + fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + } } - } else if(null != fbo) { - fbo.destroy(gl); - } - } - - @Override - protected void contextMadeCurrent(GLContext glc, boolean current) { - final GL gl = glc.getGL(); - if(current) { - fbo.bind(gl); + fbos[fboIFront].syncFramebuffer(gl); + fboBound = false; + final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities(); + fbos[0].formatToGLCapabilities(fboCapsNative); + fboCapsNative.setDoubleBuffered( fboCapsNative.getDoubleBuffered() || samples > 0 ); + + initialized = true; } else { - fbo.unbind(gl); - final TextureAttachment attachment = samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) ; - if(null == attachment) { - throw new GLException("Null texture colorbuffer, samples "+samples+", "+fbo.toString()); - } - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - fbo.use(gl, attachment ); - if( samples > 0) { - gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer()); + initialized = false; + + for(int i=0; i "+newSamples); + } + initialize(false, gl); + samples = newSamples; + initialize(true, gl); + } else { + if(DEBUG) { + System.err.println("GLFBODrawableImpl.reset(): simple reconfig: "+samples+" -> "+newSamples); + } + final int nWidth = getWidth(); + final int nHeight = getHeight(); + samples = newSamples; + pendingFBOReset = ( 1 < fbos.length ) ? fbos[fboIFront] : null; // pending-front reset only w/ double buffering (or zero samples) + for(int i=0; i 0 ) { + res = fbos[0].getSamplingSinkFBO(); + } else { + res = fbos[fboIFront]; + } + break; + case GL.GL_BACK: + res = fbos[fboIBack]; + break; + default: + throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName)); + } + return res; + } + + @Override + public final TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException { + if(!initialized) { + return null; + } + final TextureAttachment res; + switch(bufferName) { + case GL.GL_FRONT: + if( samples > 0 ) { + res = fbos[0].getSamplingSink(); + } else { + res = (TextureAttachment) fbos[fboIFront].getColorbuffer(0); + } + break; + case GL.GL_BACK: + if( samples > 0 ) { + throw new IllegalArgumentException("Cannot access GL_BACK buffer of MSAA FBO: "+this); + } else { + res = (TextureAttachment) fbos[fboIBack].getColorbuffer(0); + } + break; + default: + throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName)); + } + return res; + } + private static final String illegalBufferName = "Only GL_FRONT and GL_BACK buffer are allowed, passed "; + + @Override + public String toString() { + return getClass().getSimpleName()+"[Initialized "+initialized+", realized "+isRealized()+", texUnit "+texUnit+", samples "+samples+ + ",\n\tFactory "+getFactory()+ + ",\n\tHandle "+toHexString(getHandle())+ + ",\n\tCaps "+surface.getGraphicsConfiguration().getChosenCapabilities()+ + ",\n\tfboI back "+fboIBack+", front "+fboIFront+", num "+(initialized ? fbos.length : 0)+ + ",\n\tFBO front read "+getDefaultReadFramebuffer()+", "+getFBObject(GL.GL_FRONT)+ + ",\n\tFBO back write "+getDefaultDrawFramebuffer()+", "+getFBObject(GL.GL_BACK)+ + ",\n\tSurface "+getNativeSurface()+ + "]"; + } + + public static class ResizeableImpl extends GLFBODrawableImpl implements GLFBODrawable.Resizeable { + protected ResizeableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, ProxySurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { + super(factory, parent, surface, fboCaps, textureUnit); + } + + @Override + public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException { + if(DEBUG) { + System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + int lockRes = lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface: "+this); + } + try { + // propagate new size + final ProxySurface ps = (ProxySurface) getNativeSurface(); + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else { + throw new InternalError("GLFBODrawableImpl.ResizableImpl's ProxySurface doesn't hold a UpstreamSurfaceHookMutableSize but "+ush.getClass().getName()+", "+ps+", ush"); + } + if( null != context && context.isCreated() ) { + resetSize(context.getGL()); + } + } finally { + unlockSurface(); + } + } + } } diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index 768fc6892..79f96b64a 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -28,8 +28,12 @@ package jogamp.opengl; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; + +import com.jogamp.common.os.Platform; public class GLGraphicsConfigurationUtil { public static final String NV_coverage_sample = "NV_coverage_sample"; @@ -119,26 +123,34 @@ public class GLGraphicsConfigurationUtil { return getExclusiveWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap()); } - public static final GLCapabilities setWinAttributeBits(GLCapabilities caps, int winattrbits) { + public static final GLCapabilities fixWinAttribBitsAndHwAccel(AbstractGraphicsDevice device, int winattrbits, GLCapabilities caps) { caps.setBitmap ( 0 != ( BITMAP_BIT & winattrbits ) ); caps.setPBuffer ( 0 != ( PBUFFER_BIT & winattrbits ) ); caps.setFBO ( 0 != ( FBO_BIT & winattrbits ) ); // we reflect availability semantics, hence setting onscreen at last (maybe overwritten above)! - caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) ); - return caps; - } + caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) ); + final int accel = GLContext.isHardwareRasterizer( device, caps.getGLProfile() ); + if(0 == accel && caps.getHardwareAccelerated() ) { + caps.setHardwareAccelerated(false); + } + + return caps; + } + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { if( !capsRequested.isOnscreen() ) { return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable); - } + } /* we maintain the offscreen mode flags in onscreen mode - else { + return fixOnscreenGLCapabilities(capsRequested); + } */ return capsRequested; } public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested) { - if( !capsRequested.isOnscreen() ) { + if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) { // fix caps .. final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setBitmap (false); @@ -157,9 +169,11 @@ public class GLGraphicsConfigurationUtil { public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { final boolean auto = !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; + + final boolean requestedPBuffer = capsRequested.isPBuffer() || Platform.getOSType() == Platform.OSType.MACOS ; // no native bitmap for OSX final boolean useFBO = fboAvailable && ( auto || capsRequested.isFBO() ) ; - final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || capsRequested.isPBuffer() ) ; + final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || requestedPBuffer ) ; final boolean useBitmap = !useFBO && !usePbuffer && ( auto || capsRequested.isBitmap() ) ; if( capsRequested.isOnscreen() || diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java new file mode 100644 index 000000000..7701f209f --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java @@ -0,0 +1,123 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.opengl; + +import javax.media.nativewindow.NativeWindowException; +import javax.media.opengl.GL; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLOffscreenAutoDrawable; + +import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.GLAutoDrawableDelegate; + +import jogamp.opengl.GLFBODrawableImpl; + +public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implements GLOffscreenAutoDrawable { + + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param lock optional upstream lock, may be null + */ + public GLOffscreenAutoDrawableImpl(GLDrawable drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) { + super(drawable, context, upstreamWidget, true, lock); + } + + @Override + public void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException { + this.defaultWindowResizedOp(newWidth, newHeight); + } + + public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param lock optional upstream lock, may be null + */ + public FBOImpl(GLFBODrawableImpl drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) { + super(drawable, context, upstreamWidget, lock); + } + + @Override + public boolean isInitialized() { + return ((GLFBODrawableImpl)drawable).isInitialized(); + } + + @Override + public final int getTextureUnit() { + return ((GLFBODrawableImpl)drawable).getTextureUnit(); + } + + @Override + public final void setTextureUnit(int unit) { + ((GLFBODrawableImpl)drawable).setTextureUnit(unit); + } + + @Override + public final int getNumSamples() { + return ((GLFBODrawableImpl)drawable).getNumSamples(); + } + + @Override + public final void setNumSamples(GL gl, int newSamples) throws GLException { + ((GLFBODrawableImpl)drawable).setNumSamples(gl, newSamples); + windowRepaintOp(); + } + + /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + @Override + public DoubleBufferMode getDoubleBufferMode() { + return ((GLFBODrawableImpl)drawable).getDoubleBufferMode(); + } + + @Override + public void setDoubleBufferMode(DoubleBufferMode mode) throws GLException { + ((GLFBODrawableImpl)drawable).setDoubleBufferMode(mode); + } */ + + @Override + public final FBObject getFBObject(int bufferName) { + return ((GLFBODrawableImpl)drawable).getFBObject(bufferName); + } + + public final FBObject.TextureAttachment getTextureBuffer(int bufferName) { + return ((GLFBODrawableImpl)drawable).getTextureBuffer(bufferName); + } + + @Override + public void resetSize(GL gl) throws GLException { + ((GLFBODrawableImpl)drawable).resetSize(gl); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index 32f4cb696..b438131bc 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -40,9 +40,6 @@ package jogamp.opengl; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLPbuffer; @@ -50,36 +47,18 @@ import javax.media.opengl.GLPbuffer; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; -/** Platform-independent class exposing pbuffer functionality to - applications. This class is not exposed in the public API as it - would probably add no value; however it implements the GLDrawable - interface so can be interacted with via its display() method. */ - +@SuppressWarnings("deprecation") public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { private int floatMode; - public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) { - super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable - - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) - drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); - if(caps.isOnscreen()) { - if(caps.isPBuffer()) { - throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable); - } - throw new IllegalArgumentException("Error: Given drawable is Onscreen: "+pbufferDrawable); - } else { - if(!caps.isPBuffer()) { - throw new IllegalArgumentException("Error: Given drawable is not Pbuffer: "+pbufferDrawable); - } - } - context = (GLContextImpl) drawable.createContext(sharedContext); + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) { + super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext } // // pbuffer specifics - // - + // + @Override public void bindTexture() { // Doesn't make much sense to try to do this on the event dispatch diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 03d0d650f..06953a8e1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -282,12 +282,6 @@ public abstract class EGLContext extends GLContextImpl { return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); } - @Override - public abstract void bindPbufferToTexture(); - - @Override - public abstract void releasePbufferFromTexture(); - // // Accessible .. // diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index 0dba4bb09..167eebf3a 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,7 +36,8 @@ package jogamp.opengl.egl; -import javax.media.nativewindow.MutableSurface; +import java.nio.IntBuffer; + import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.ProxySurface; @@ -46,10 +47,10 @@ import javax.media.opengl.GLException; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLSurface = false; // for destruction protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); @@ -58,21 +59,14 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle); - private final void recreateSurface() { - final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); - if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using "+eglConfig); - } - if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { - EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); - } + private final long createEGLSurface() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration(); + final NativeSurface upstreamSurface = eglws.getUpstreamSurface(); - final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); - final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); - long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + long eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), upstreamSurface.getSurfaceHandle()); int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { @@ -86,7 +80,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglConfig, nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } @@ -99,34 +93,53 @@ public abstract class EGLDrawable extends GLDrawableImpl { if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); } - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface)); } - - ((MutableSurface)surface).setSurfaceHandle(eglSurface); + return eglSurface; } @Override protected final void updateHandle() { - if(ownEGLSurface) { - recreateSurface(); + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": updateHandle of "+eglws); + } + if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) { + throw new InternalError("Set surface but claimed to be invalid: "+eglws); + } + eglws.setSurfaceHandle( createEGLSurface() ); + } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } + } + + protected void destroyHandle() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": destroyHandle of "+eglws); + } + if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglws.getGraphicsConfiguration().getScreen().getDevice(); + if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + EGL.eglDestroySurface(eglDevice.getHandle(), eglws.getSurfaceHandle()); + eglws.setSurfaceHandle(EGL.EGL_NO_SURFACE); } } - protected static boolean isValidEGLSurface(EGLGraphicsDevice eglDevice, NativeSurface surface) { - final long eglDisplayHandle = eglDevice.getHandle(); - if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + protected static boolean isValidEGLSurface(long eglDisplayHandle, long surfaceHandle) { + if( 0 == surfaceHandle ) { + return false; } - boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); - if(eglSurfaceValid) { - int[] tmp = new int[1]; - eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); - if(!eglSurfaceValid) { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); - } + final IntBuffer val = Buffers.newDirectIntBuffer(1); + final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surfaceHandle, EGL.EGL_CONFIG_ID, val); + if( !eglSurfaceValid ) { + final int eglErr = EGL.eglGetError(); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle)); } } return eglSurfaceValid; @@ -134,55 +147,19 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { - final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); - if (realized) { - final boolean eglSurfaceValid = isValidEGLSurface(eglDevice, surface); - if(eglSurfaceValid) { - // surface holds valid EGLSurface - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle())); - } - ownEGLSurface=false; - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - // However .. let's validate the surface object first - if( ! (surface instanceof ProxySurface) ) { - throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface); - } - final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); - if( null == upstreamHook ) { - throw new InternalError("null upstreamHook of: "+surface); - } - if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { - throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); - } - if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { - throw new InternalError("null upstream surface"); - } - ownEGLSurface=true; - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); - } - } - } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); - } - // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { - throw new GLException("Error destroying window surface (eglDestroySurface)"); - } - ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealized("+realized+"): NOP - "+surface); } } @Override - protected final void swapBuffersImpl() { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { - throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { + throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + } } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 292eb17c8..e98d69140 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -52,8 +52,7 @@ import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; -import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; @@ -65,6 +64,7 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; @@ -76,10 +76,11 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); @@ -112,7 +113,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + defaultDevice = new EGLGraphicsDevice(); // FIXME: Probably need to move EGL from a static model // to a dynamic one, where there can be 2 instances @@ -310,6 +311,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { try { final GLCapabilities reqCapsAny = new GLCapabilities(glp); reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0); + reqCapsAny.setDoubleBuffered(false); final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); final List availablePBufferCapsL = getAvailableEGLConfigs(sharedEGLDevice, reqCapsPBuffer); hasPBuffer[0] = availablePBufferCapsL.size() > 0; @@ -324,18 +326,20 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } else { final List capsAnyL = getAvailableEGLConfigs(eglDevice, reqCapsAny); if(capsAnyL.size() > 0) { - final GLCapabilitiesImmutable caps = capsAnyL.get(0); - EGLContext.mapStaticGLESVersion(eglDevice, caps); + final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0); + EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps); if(eglDevice != adevice) { - EGLContext.mapStaticGLESVersion(adevice, caps); + EGLContext.mapStaticGLESVersion(adevice, chosenCaps); } + final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null); + EGLContext.mapStaticGLESVersion(adeviceEGLDevice, chosenCaps); success = true; } if(DEBUG) { System.err.println("EGLDrawableFactory.isEGLContextAvailable() no pbuffer config available, detected !pbuffer config: "+success); EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err); } - } + } } else { surface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; @@ -361,6 +365,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(eglDevice != adevice) { context.mapCurrentAvailableGLVersion(adevice); } + final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null); + context.mapCurrentAvailableGLVersion(adeviceEGLDevice); success = true; } else { // Oops .. something is wrong @@ -538,70 +544,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, getEGLSurface(target)); + return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); } - protected static NativeSurface getEGLSurface(NativeSurface surface) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { - if(surface instanceof WrappedSurface) { - // already wrapped surface - no wrapped recursion - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - already wrapped surface - use as-is: "+surface); - } - return surface; - } - if(EGLDrawable.isValidEGLSurface((EGLGraphicsDevice)aDevice, surface)) { - // already in native EGL format - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - already valid EGL surface - use as-is: "+surface); - } - return surface; - } - } - // create EGL instance out of platform native types - final EGLGraphicsDevice eglDevice; - if( aDevice instanceof EGLGraphicsDevice ) { - eglDevice = (EGLGraphicsDevice) aDevice; - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - Reusing eglDevice: "+eglDevice); - } - if(0 == eglDevice.getHandle()) { - eglDevice.open(); - } - } else { - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface); - } - final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - final EGLGraphicsConfiguration eglConfig; - if( aConfig instanceof EGLGraphicsConfiguration ) { - // Config is already in EGL type - reuse .. - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if( 0 == capsChosen.getEGLConfig() ) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); - if( 0 == capsChosen.getEGLConfig() ) { - throw new GLException("Refreshing native EGLConfig handle failed with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); - } else if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig); - } - } - return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface)); - } static String getThreadName() { return Thread.currentThread().getName(); } @Override @@ -615,7 +560,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Non pbuffer not yet implemented"); } // PBuffer GLDrawable Creation - return new EGLPbufferDrawable(this, getEGLSurface(target)); + return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target)); } @Override @@ -628,20 +573,24 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { + final boolean ownDevice; final EGLGraphicsDevice device; - if(createNewDevice) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + if(createNewDevice || ! ( deviceReq instanceof EGLGraphicsDevice ) ) { + final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ? + ( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID()); + ownDevice = true; } else { device = (EGLGraphicsDevice) deviceReq; + ownDevice = false; } final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, ownDevice); } @Override @@ -649,54 +598,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixDoubleBufferedGLCapabilities( - GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)), - false); - return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)), false); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); } - private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { - if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); - if(0 == eglDevice.getHandle()) { - eglDevice.open(); - s.setImplBitfield(ProxySurface.OWN_DEVICE); - } - createPBufferSurfaceImpl(s, false); - if(DEBUG) { - System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); - } - } - } - @Override - public final void destroy(ProxySurface s) { - if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { - final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration(); - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); - EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); - s.setSurfaceHandle(EGL.EGL_NO_SURFACE); - if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { - eglDevice.close(); - } - if(DEBUG) { - System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); - } - } - } - @Override - public final int getWidth(ProxySurface s) { - return s.initialWidth; - } - @Override - public final int getHeight(ProxySurface s) { - return s.initialHeight; - } - @Override - public String toString() { - return "EGLSurfaceLifecycleHook[]"; - } - - }; /** * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. @@ -705,7 +609,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle */ protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { - final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration(); + return null; + } + protected static long createPBufferSurfaceImpl(EGLGraphicsConfiguration config, int width, int height, boolean useTexture) { final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final int texFormat; @@ -720,15 +626,14 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { System.out.println("Pbuffer config: " + config); } - final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(width, height, texFormat); final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0); if (EGL.EGL_NO_SURFACE==surf) { - throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+width+"x"+height+", "+eglDevice+", "+config+", error 0x"+Integer.toHexString(EGL.eglGetError())); } else if(DEBUG) { System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); } - ms.setSurfaceHandle(surf); - return ms; + return surf; } @Override @@ -737,7 +642,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); + return new WrappedSurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..b172d4f35 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java @@ -0,0 +1,49 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public EGLDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + s.setSurfaceHandle( EGLDrawableFactory.createPBufferSurfaceImpl((EGLGraphicsConfiguration)s.getGraphicsConfiguration(), 64, 64, false) ); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no EGL surface: "+s); + } + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 585638d21..84bd705db 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -79,15 +79,4 @@ public class EGLExternalContext extends EGLContext { @Override protected void destroyImpl() throws GLException { } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java index e513a86cf..f857c6b5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java @@ -57,8 +57,8 @@ public class EGLGLCapabilities extends GLCapabilities { this.eglcfg = eglcfg; this.eglcfgid = eglcfgid; if(!isCompatible(glp, renderableType)) { - throw new GLException("Incompatible "+glp+ - " with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); + throw new GLException("Requested GLProfile "+glp+ + " not compatible with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); } this.renderableType = renderableType; this.nativeVisualID = visualID; @@ -131,6 +131,7 @@ public class EGLGLCapabilities extends GLCapabilities { sink = new StringBuilder(); } boolean first=true; + sink.append("0x").append(Integer.toHexString(renderableType)).append(": "); if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) { sink.append("GL"); first=false; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 8ee98072f..7bf201238 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -211,6 +211,13 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple if(null == glp) { glp = EGLGLCapabilities.getCompatible(device, rType); } + if(!EGLGLCapabilities.isCompatible(glp, rType)) { + if(DEBUG) { + System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+ + " not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]"); + } + return null; + } caps = new EGLGLCapabilities(config, cfgID, visualID, glp, rType); } catch (GLException gle) { if(DEBUG) { @@ -288,7 +295,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple return null; } - return (EGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(caps, drawableTypeBits); + return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps); } public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java index eae47fa92..325ad6142 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java @@ -41,16 +41,5 @@ public class EGLOnscreenContext extends EGLContext { public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) { super(drawable, shareWith); } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java index d54057775..6440cf1e5 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java @@ -54,8 +54,8 @@ public class EGLOnscreenDrawable extends EGLDrawable { } @Override - protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) { + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); - } + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java index 7175d516f..bb9eeb892 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java @@ -46,15 +46,5 @@ public class EGLPbufferContext extends EGLContext { public int getFloatingPointMode() { return 0; // FIXME ?? } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Not yet implemented"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Not yet implemented"); - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index 4a36625bd..eb7e320c8 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -52,12 +52,8 @@ public class EGLPbufferDrawable extends EGLDrawable { } @Override - protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) { - final MutableSurface ms = (MutableSurface)getNativeSurface(); - if(config != ms.getGraphicsConfiguration()) { - throw new InternalError("Not same: "+config.hashCode()+", "+ms.getGraphicsConfiguration()+": "+config+", "+ms.getGraphicsConfiguration()); - } - return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle(); + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { + return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java index 42c6e100e..342c4c417 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -1,38 +1,163 @@ package jogamp.opengl.egl; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; -public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook { +public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { + protected static final boolean DEBUG = EGLDrawableFactory.DEBUG; private final NativeSurface upstreamSurface; + private final UpstreamSurfaceHook.MutableSize upstreamSurfaceHookMutableSize; public EGLUpstreamSurfaceHook(NativeSurface upstream) { upstreamSurface = upstream; + if(upstreamSurface instanceof ProxySurface) { + final UpstreamSurfaceHook ush = ((ProxySurface)upstreamSurface).getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + // offscreen NativeSurface w/ MutableSize (default) + upstreamSurfaceHookMutableSize = (UpstreamSurfaceHook.MutableSize) ush; + } else { + upstreamSurfaceHookMutableSize = null; + } + } else { + upstreamSurfaceHookMutableSize = null; + } } public final NativeSurface getUpstreamSurface() { return upstreamSurface; } + static String getThreadName() { return Thread.currentThread().getName(); } + + public final void setSize(int width, int height) { + if(null != upstreamSurfaceHookMutableSize) { + upstreamSurfaceHookMutableSize.setSize(width, height); + } + } + @Override public final void create(ProxySurface surface) { + final String dbgPrefix; + if(DEBUG) { + dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create("+surface.getClass().getSimpleName()+"): "; + System.err.println(dbgPrefix+this); + } else { + dbgPrefix = null; + } + if(upstreamSurface instanceof ProxySurface) { + // propagate createNotify(..) so upstreamSurface will be created ((ProxySurface)upstreamSurface).createNotify(); - if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { - throw new GLException("Could not lock: "+upstreamSurface); + } + + // lock upstreamSurface, so it can be used in case EGLDisplay is derived from it! + if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { + throw new GLException("Could not lock: "+upstreamSurface); + } + try { + evalUpstreamSurface(dbgPrefix, surface); + } finally { + upstreamSurface.unlockSurface(); + } + } + + private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) { + // + // evaluate nature of upstreamSurface, may create EGL instances if required + // + + boolean isEGLSurfaceValid = true; // assume yes + + final AbstractGraphicsConfiguration aConfig = upstreamSurface.getGraphicsConfiguration(); + final AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + + final EGLGraphicsDevice eglDevice; + if( aDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) aDevice; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing eglDevice: "+eglDevice); + } + if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) { + eglDevice.open(); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } else { + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( !isEGLSurfaceValid || !EGLGraphicsConfiguration.isEGLConfigValid(eglDevice.getHandle(), capsChosen.getEGLConfig()) ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+capsChosen+" of "+aConfig); + } + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(dbgPrefix+"Refreshing eglConfig: "+eglConfig); + } + isEGLSurfaceValid = false; + } else { + eglConfig = (EGLGraphicsConfiguration) aConfig; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing eglConfig: "+eglConfig); + } + } + } else { + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(dbgPrefix+"Chosen eglConfig: "+eglConfig); } + isEGLSurfaceValid = false; } - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - eglDevice.open(); + surface.setGraphicsConfiguration(eglConfig); + + if(isEGLSurfaceValid) { + isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); + } + if(isEGLSurfaceValid) { + surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle()); + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: Already valid EGL surface - use as-is: "+upstreamSurface); + } + } else { + surface.setSurfaceHandle(EGL.EGL_NO_SURFACE); + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); // create/destroy in EGLDrawable + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: EGL surface n/a - TBD: "+upstreamSurface); + } + } } @Override public final void destroy(ProxySurface surface) { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - eglDevice.close(); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this); + } + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); if(upstreamSurface instanceof ProxySurface) { - upstreamSurface.unlockSurface(); ((ProxySurface)upstreamSurface).destroyNotify(); } } @@ -49,8 +174,8 @@ public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook @Override public String toString() { - final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil"; - return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]"; + final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": 0x" + Long.toHexString(upstreamSurface.getSurfaceHandle()) ) : "nil"; + return "EGLUpstreamSurfaceHook[ "+ upstreamSurface.getWidth() + "x" + upstreamSurface.getHeight() + ", " + us_s+ "]"; } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java new file mode 100644 index 000000000..b36303392 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java @@ -0,0 +1,26 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; + +import jogamp.nativewindow.WrappedSurface; + +public class EGLWrappedSurface extends WrappedSurface { + + public static EGLWrappedSurface get(NativeSurface surface) { + if(surface instanceof EGLWrappedSurface) { + return (EGLWrappedSurface)surface; + } + return new EGLWrappedSurface(surface); + } + + public EGLWrappedSurface(NativeSurface surface) { + super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLWrappedSurface.ctor(): "+this); + } + } + + public final NativeSurface getUpstreamSurface() { + return ((EGLUpstreamSurfaceHook)super.getUpstreamSurfaceHook()).getUpstreamSurface(); + } +} diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 55aea3a98..ec29558d1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -49,6 +49,7 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -58,6 +59,7 @@ import javax.media.opengl.GLProfile; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLFBODrawableImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -76,9 +78,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl boolean isNSContext(); long create(long share, int ctp, int major, int minor); boolean destroy(long ctx); + boolean contextRealized(boolean realized); boolean copyImpl(long src, int mask); boolean makeCurrent(long ctx); boolean release(long ctx); + boolean detachPBuffer(); boolean setSwapInterval(int interval); boolean swapBuffers(); } @@ -279,7 +283,24 @@ public abstract class MacOSXCGLContext extends GLContextImpl throw new GLException("Error destroying OpenGL Context: "+this); } } + + @Override + protected void contextRealized(boolean realized) { + // context stuff depends on drawable stuff + if(realized) { + super.contextRealized(true); // 1) init drawable stuff + impl.contextRealized(true); // 2) init context stuff + } else { + impl.contextRealized(false); // 1) free context stuff + super.contextRealized(false); // 2) free drawable stuff + } + } + + /* pp */ void detachPBuffer() { + impl.detachPBuffer(); + } + @Override protected void copyImpl(GLContext source, int mask) throws GLException { if( isNSContext() != ((MacOSXCGLContext)source).isNSContext() ) { @@ -365,16 +386,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl throw new GLException("Should not call this"); } - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - // Support for "mode switching" as described in MacOSXCGLDrawable public void setOpenGLMode(GLBackendType mode) { if (mode == openGLMode) { @@ -421,323 +432,486 @@ public abstract class MacOSXCGLContext extends GLContextImpl // NSOpenGLContext-based implementation class NSOpenGLImpl implements GLBackendImpl { - long nsOpenGLLayer = 0; - long nsOpenGLLayerPFmt = 0; - float screenVSyncTimeout; // microSec - int vsyncTimeout; // microSec - for nsOpenGLLayer mode - - @Override - public boolean isNSContext() { return true; } - - @Override - public long create(long share, int ctp, int major, int minor) { - long ctx = 0; - final long nsViewHandle; - if(drawable instanceof MacOSXCGLDrawable) { - // we allow null here! (special pbuffer case) - nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle(); - } else { - // we only allow a valid NSView here - final long aHandle = drawable.getHandle(); - if( OSXUtil.isNSView(aHandle) ) { - nsViewHandle = aHandle; - } else { - throw new RuntimeException("Anonymous drawable instance's handle not of type NSView: "+drawable.getClass().getName()+", "+drawable); - } - } - final NativeSurface surface = drawable.getNativeSurface(); - final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); - final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); - - boolean allowIncompleteView = null != backingLayerHost; - if( !allowIncompleteView && surface instanceof ProxySurface ) { - allowIncompleteView = 0 != ( ProxySurface.INVISIBLE_WINDOW & ((ProxySurface)surface).getImplBitfield() ) ; - } - final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor); - if (pixelFormat == 0) { - if(DEBUG) { - System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps); - } - return 0; - } - config.setChosenPixelFormat(pixelFormat); - int sRefreshRate = CGL.getScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex()); - screenVSyncTimeout = 1000000f / sRefreshRate; - if(DEBUG) { - System.err.println("NS create OSX>=lion "+isLionOrLater); - System.err.println("NS create allowIncompleteView: "+allowIncompleteView); - System.err.println("NS create backingLayerHost: "+backingLayerHost); - System.err.println("NS create share: "+share); - System.err.println("NS create chosenCaps: "+chosenCaps); - System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); - System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); - System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle)); - System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); - // Thread.dumpStack(); - } - try { - int[] viewNotReady = new int[1]; - // Try to allocate a context with this - ctx = CGL.createContext(share, - nsViewHandle, allowIncompleteView, - pixelFormat, - chosenCaps.isBackgroundOpaque(), - viewNotReady, 0); - if (0 == ctx) { - if(DEBUG) { - System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0])); - } - return 0; - } + private OffscreenLayerSurface backingLayerHost = null; + private long nsOpenGLLayer = 0; + private long nsOpenGLLayerPFmt = 0; + private float screenVSyncTimeout; // microSec + private int vsyncTimeout; // microSec - for nsOpenGLLayer mode + private int lastWidth=0, lastHeight=0; // allowing to detect size change + private long lastPBufferHandle = 0; // allowing to detect pbuffer recreation + + @Override + public boolean isNSContext() { return true; } + + @Override + public long create(long share, int ctp, int major, int minor) { + long ctx = 0; + final NativeSurface surface = drawable.getNativeSurface(); + final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final long nsViewHandle; + final boolean isPBuffer; + final boolean isFBO; + if(drawable instanceof GLFBODrawableImpl) { + nsViewHandle = 0; + isPBuffer = false; + isFBO = true; + if(DEBUG) { + System.err.println("NS create GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + } else if(drawable instanceof MacOSXCGLDrawable) { + // we allow null here! (special pbuffer case) + nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle(); + isPBuffer = CGL.isNSOpenGLPixelBuffer(drawable.getHandle()); + isFBO = false; + if(DEBUG) { + System.err.println("NS create MacOSXCGLDrawable drawable handle isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + } else { + // we only allow a valid NSView here + final long drawableHandle = drawable.getHandle(); + final boolean isNSView = OSXUtil.isNSView(drawableHandle); + final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle); + isPBuffer = CGL.isNSOpenGLPixelBuffer(drawableHandle); + isFBO = false; - if (!chosenCaps.isPBuffer() && !chosenCaps.isBackgroundOpaque()) { - // Set the context opacity - CGL.setContextOpacity(ctx, 0); + if(DEBUG) { + System.err.println("NS create Anonymous drawable handle "+toHexString(drawableHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + if( isNSView ) { + nsViewHandle = drawableHandle; + } else if( isNSWindow ) { + nsViewHandle = OSXUtil.GetNSView(drawableHandle); + } else if( isPBuffer ) { + nsViewHandle = 0; + } else { + throw new RuntimeException("Anonymous drawable instance's handle neither NSView, NSWindow nor PBuffer: "+toHexString(drawableHandle)+", "+drawable.getClass().getName()+",\n\t"+drawable); + } } + backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + boolean allowIncompleteView = null != backingLayerHost; + if( !allowIncompleteView && surface instanceof ProxySurface ) { + allowIncompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE ); + } + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor); + if (pixelFormat == 0) { + if(DEBUG) { + System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps); + } + return 0; + } GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat); - fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); - if(!fixedCaps.isPBuffer()) { + if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) { // not handled, so copy them fixedCaps.setFBO(chosenCaps.isFBO()); + fixedCaps.setPBuffer(chosenCaps.isPBuffer()); fixedCaps.setBitmap(chosenCaps.isBitmap()); fixedCaps.setOnscreen(chosenCaps.isOnscreen()); } - config.setChosenCapabilities(fixedCaps); + fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); + int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex()); + screenVSyncTimeout = 1000000f / sRefreshRate; if(DEBUG) { + System.err.println("NS create OSX>=lion "+isLionOrLater); + System.err.println("NS create allowIncompleteView: "+allowIncompleteView); + System.err.println("NS create backingLayerHost: "+backingLayerHost); + System.err.println("NS create share: "+share); + System.err.println("NS create drawable type: "+drawable.getClass().getName()); + System.err.println("NS create drawable handle: isPBuffer "+isPBuffer+", isFBO "+isFBO); + System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); + System.err.println("NS create chosenCaps: "+chosenCaps); System.err.println("NS create fixedCaps: "+fixedCaps); + System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); + System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle)); + System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); + // Thread.dumpStack(); } if(fixedCaps.isPBuffer()) { - // Must now associate the pbuffer with our newly-created context - CGL.setContextPBuffer(ctx, drawable.getHandle()); + if(!isPBuffer) { + throw new InternalError("fixedCaps is PBuffer, handle not: "+drawable); + } + } else { + if(isPBuffer) { + throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable); + } } - // - // handled layered surface - // + config.setChosenCapabilities(fixedCaps); + /** if(null != backingLayerHost) { - nsOpenGLLayerPFmt = pixelFormat; - pixelFormat = 0; - final int texWidth, texHeight; - if(drawable instanceof MacOSXPbufferCGLDrawable) { - final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; - texWidth = osxPDrawable.getTextureWidth(); - texHeight = osxPDrawable.getTextureHeight(); - } else { - texWidth = drawable.getWidth(); - texHeight = drawable.getHeight(); + backingLayerHost.setChosenCapabilities(fixedCaps); + } */ + + try { + int[] viewNotReady = new int[1]; + // Try to allocate a context with this + ctx = CGL.createContext(share, + nsViewHandle, allowIncompleteView, + pixelFormat, + chosenCaps.isBackgroundOpaque(), + viewNotReady, 0); + if (0 == ctx) { + if(DEBUG) { + System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0])); + } + return 0; } - if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) { - throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable); + + if(null != backingLayerHost) { + nsOpenGLLayerPFmt = pixelFormat; + pixelFormat = 0; } - nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight); - if (DEBUG) { - System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable); + + if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) { + // Set the context opacity + CGL.setContextOpacity(ctx, 0); + } + } finally { + if(0!=pixelFormat) { + CGL.deletePixelFormat(pixelFormat); + pixelFormat = 0; } - backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); - setSwapInterval(1); // enabled per default in layered surface - } - } finally { - if(0!=pixelFormat) { - CGL.deletePixelFormat(pixelFormat); - } - } - return ctx; - } - - @Override - public boolean destroy(long ctx) { - if(0 != nsOpenGLLayer) { - final NativeSurface surface = drawable.getNativeSurface(); - if (DEBUG) { - System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)); - } - final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); - if(null != ols && ols.isSurfaceLayerAttached()) { - // still having a valid OLS attached to surface (parent OLS could have been removed) - ols.detachSurfaceLayer(); } - CGL.releaseNSOpenGLLayer(nsOpenGLLayer); - CGL.deletePixelFormat(nsOpenGLLayerPFmt); - nsOpenGLLayerPFmt = 0; - nsOpenGLLayer = 0; + return ctx; } - return CGL.deleteContext(ctx, true); - } - - @Override - public boolean copyImpl(long src, int mask) { - CGL.copyContext(contextHandle, src, mask); - return true; - } - @Override - public boolean makeCurrent(long ctx) { - final long cglCtx = CGL.getCGLContext(ctx); - if(0 == cglCtx) { - throw new InternalError("Null CGLContext for: "+this); + @Override + public boolean destroy(long ctx) { + lastPBufferHandle = 0; + return CGL.deleteContext(ctx, true); } - int err = CGL.CGLLockContext(cglCtx); - if(CGL.kCGLNoError == err) { - return CGL.makeCurrentContext(ctx); - } else if(DEBUG) { - System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean contextRealized(boolean realized) { + if( realized ) { + if( null != backingLayerHost ) { + // + // handled layered surface + // + final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities(); + final long ctx = MacOSXCGLContext.this.getHandle(); + final int texID; + final long drawableHandle = drawable.getHandle(); + if(drawable instanceof GLFBODrawableImpl) { + final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable; + texID = fbod.getTextureBuffer(GL.GL_FRONT).getName(); + fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() { + public void swapBuffers(boolean doubleBuffered) { + MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers(); + } } ) ; + lastPBufferHandle = 0; + } else if( chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) { + texID = 0; + lastPBufferHandle = drawableHandle; + } else { + throw new GLException("BackingLayerHost w/ unknown handle (!FBO, !PBuffer): "+drawable); + } + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) { + throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable); + } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, lastPBufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); + if (DEBUG) { + System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(lastPBufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable); + } + backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); + setSwapInterval(1); // enabled per default in layered surface + } else { + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + } + } else { + if( 0 != nsOpenGLLayer ) { + final NativeSurface surface = drawable.getNativeSurface(); + if (DEBUG) { + System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable); + } + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + if(null != ols && ols.isSurfaceLayerAttached()) { + // still having a valid OLS attached to surface (parent OLS could have been removed) + ols.detachSurfaceLayer(); + } + CGL.releaseNSOpenGLLayer(nsOpenGLLayer); + nsOpenGLLayer = 0; + } + if(0 != nsOpenGLLayerPFmt) { + CGL.deletePixelFormat(nsOpenGLLayerPFmt); + nsOpenGLLayerPFmt = 0; + } + lastPBufferHandle = 0; + } + backingLayerHost = null; + return true; } - return false; - } - @Override - public boolean release(long ctx) { - try { - gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze - } catch (GLException gle) { - if(DEBUG) { - System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:"); - gle.printStackTrace(); + private final void validatePBufferConfig(long ctx) { + final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities(); + final long drawableHandle = drawable.getHandle(); + if(chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) && lastPBufferHandle != drawableHandle) { + // Must associate the pbuffer with our newly-created context + lastPBufferHandle = drawableHandle; + if(0 != drawableHandle) { + CGL.setContextPBuffer(ctx, drawableHandle); + } + if(DEBUG) { + System.err.println("NS.validateDrawableConfig bind pbuffer "+toHexString(drawableHandle)+" -> ctx "+toHexString(ctx)); + } } } - final boolean res = CGL.clearCurrentContext(ctx); - final long cglCtx = CGL.getCGLContext(ctx); - if(0 == cglCtx) { - throw new InternalError("Null CGLContext for: "+this); + + /** Returns true if size has been updated, otherwise false (same size). */ + private final boolean validateDrawableSizeConfig(long ctx) { + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + if( lastWidth != width || lastHeight != height ) { + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + if(DEBUG) { + System.err.println("NS.validateDrawableConfig size changed"); + } + return true; + } + return false; } - final int err = CGL.CGLUnlockContext(cglCtx); - if(DEBUG && CGL.kCGLNoError != err) { - System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean copyImpl(long src, int mask) { + CGL.copyContext(contextHandle, src, mask); + return true; } - return res && CGL.kCGLNoError == err; - } - @Override - public boolean setSwapInterval(int interval) { - if(0 != nsOpenGLLayer) { - CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); - vsyncTimeout = interval * (int)screenVSyncTimeout; - if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); } + @Override + public boolean makeCurrent(long ctx) { + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + int err = CGL.CGLLockContext(cglCtx); + if(CGL.kCGLNoError == err) { + validatePBufferConfig(ctx); // required to handle pbuffer change ASAP + return CGL.makeCurrentContext(ctx); + } else if(DEBUG) { + System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return false; + } + + @Override + public boolean release(long ctx) { + try { + gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze + } catch (GLException gle) { + if(DEBUG) { + System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:"); + gle.printStackTrace(); + } + } + final boolean res = CGL.clearCurrentContext(ctx); + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + final int err = CGL.CGLUnlockContext(cglCtx); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return res && CGL.kCGLNoError == err; } - CGL.setSwapInterval(contextHandle, interval); - return true; - } - @Override - public boolean swapBuffers() { - if( 0 != nsOpenGLLayer ) { - // If v-sync is disabled, frames will be drawn as quickly as possible - // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync). - CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout); + @Override + public boolean detachPBuffer() { + if(0 != lastPBufferHandle) { + lastPBufferHandle = 0; + if(0 != nsOpenGLLayer) { + CGL.flushNSOpenGLLayerPBuffer(nsOpenGLLayer); // notify invalid pbuffer + } + // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil + } + return true; } - if(CGL.flushBuffer(contextHandle)) { + + @Override + public boolean setSwapInterval(int interval) { if(0 != nsOpenGLLayer) { - // trigger CALayer to update - CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer); + CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); + vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms + if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); } } + CGL.setSwapInterval(contextHandle, interval); return true; } - return false; - } + + private int skipSync=0; + + @Override + public boolean swapBuffers() { + final boolean res; + if( 0 != nsOpenGLLayer ) { + if( validateDrawableSizeConfig(contextHandle) ) { + // skip wait-for-vsync for a few frames if size has changed, + // allowing to update the texture IDs ASAP. + skipSync = 10; + } + + final int texID; + final boolean valid; + if(drawable instanceof GLFBODrawableImpl) { + texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName(); + valid = 0 != texID; + } else { + texID = 0; + valid = 0 != lastPBufferHandle; + } + if(valid) { + if(0 == skipSync) { + // If v-sync is disabled, frames will be drawn as quickly as possible + // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync). + CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout); + } else { + skipSync--; + } + res = CGL.flushBuffer(contextHandle); + if(res) { + // trigger CALayer to update incl. possible surface change + CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer, lastPBufferHandle, texID, lastWidth, lastHeight); + } + } else { + res = true; + } + } else { + res = CGL.flushBuffer(contextHandle); + } + return res; + } + } class CGLImpl implements GLBackendImpl { - @Override - public boolean isNSContext() { return false; } - - @Override - public long create(long share, int ctp, int major, int minor) { - long ctx = 0; - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor); - if (pixelFormat == 0) { - throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); - } - config.setChosenPixelFormat(pixelFormat); - try { - // Create new context - PointerBuffer ctxPB = PointerBuffer.allocateDirect(1); - if (DEBUG) { - System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + @Override + public boolean isNSContext() { return false; } + + @Override + public long create(long share, int ctp, int major, int minor) { + long ctx = 0; + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor); + if (pixelFormat == 0) { + throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); } - int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB); - if (res != CGL.kCGLNoError) { - throw new GLException("Error code " + res + " while creating context"); - } - if(chosenCaps.isPBuffer()) { - // Attach newly-created context to the pbuffer - res = CGL.CGLSetPBuffer(ctxPB.get(0), drawable.getHandle(), 0, 0, 0); + try { + // Create new context + PointerBuffer ctxPB = PointerBuffer.allocateDirect(1); + if (DEBUG) { + System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + } + int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB); if (res != CGL.kCGLNoError) { - throw new GLException("Error code " + res + " while attaching context to pbuffer"); + throw new GLException("Error code " + res + " while creating context"); } - } - ctx = ctxPB.get(0); - if(0!=ctx) { - if(DEBUG) { - GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat); - System.err.println("NS created: "+caps0); + ctx = ctxPB.get(0); + + if (0 != ctx) { + GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat); + fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); + if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) { + // not handled, so copy them + fixedCaps.setFBO(chosenCaps.isFBO()); + fixedCaps.setPBuffer(chosenCaps.isPBuffer()); + fixedCaps.setBitmap(chosenCaps.isBitmap()); + fixedCaps.setOnscreen(chosenCaps.isOnscreen()); + } + config.setChosenCapabilities(fixedCaps); + if(DEBUG) { + System.err.println("CGL create fixedCaps: "+fixedCaps); + } + if(fixedCaps.isPBuffer()) { + // Must now associate the pbuffer with our newly-created context + res = CGL.CGLSetPBuffer(ctx, drawable.getHandle(), 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while attaching context to pbuffer"); + } + } } + } finally { + CGL.CGLDestroyPixelFormat(pixelFormat); } - } finally { - CGL.CGLDestroyPixelFormat(pixelFormat); + return ctx; } - return ctx; - } - @Override - public boolean destroy(long ctx) { - return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError; - } + @Override + public boolean destroy(long ctx) { + return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError; + } - @Override - public boolean copyImpl(long src, int mask) { - CGL.CGLCopyContext(src, contextHandle, mask); - return true; - } + @Override + public boolean contextRealized(boolean realized) { + return true; + } + + @Override + public boolean copyImpl(long src, int mask) { + CGL.CGLCopyContext(src, contextHandle, mask); + return true; + } - @Override - public boolean makeCurrent(long ctx) { - int err = CGL.CGLLockContext(ctx); - if(CGL.kCGLNoError == err) { - err = CGL.CGLSetCurrentContext(ctx); + @Override + public boolean makeCurrent(long ctx) { + int err = CGL.CGLLockContext(ctx); if(CGL.kCGLNoError == err) { - return true; + err = CGL.CGLSetCurrentContext(ctx); + if(CGL.kCGLNoError == err) { + return true; + } else if(DEBUG) { + System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this); + } } else if(DEBUG) { - System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this); + System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); } - } else if(DEBUG) { - System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + return false; } - return false; - } - @Override - public boolean release(long ctx) { - try { - gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze - } catch (GLException gle) { - if(DEBUG) { - System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:"); - gle.printStackTrace(); + @Override + public boolean release(long ctx) { + try { + gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze + } catch (GLException gle) { + if(DEBUG) { + System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:"); + gle.printStackTrace(); + } } + int err = CGL.CGLSetCurrentContext(0); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this); + } + int err2 = CGL.CGLUnlockContext(ctx); + if(DEBUG && CGL.kCGLNoError != err2) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this); + } + return CGL.kCGLNoError == err && CGL.kCGLNoError == err2; + } + + @Override + public boolean detachPBuffer() { + /* Doesn't work, i.e. not taking NULL + final int res = CGL.CGLSetPBuffer(contextHandle, 0, 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while detaching context from pbuffer"); + } */ + return true; } - int err = CGL.CGLSetCurrentContext(0); - if(DEBUG && CGL.kCGLNoError != err) { - System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean setSwapInterval(int interval) { + int[] lval = new int[] { interval } ; + CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); + return true; } - int err2 = CGL.CGLUnlockContext(ctx); - if(DEBUG && CGL.kCGLNoError != err2) { - System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this); + @Override + public boolean swapBuffers() { + return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); } - return CGL.kCGLNoError == err && CGL.kCGLNoError == err2; - } - - @Override - public boolean setSwapInterval(int interval) { - int[] lval = new int[] { interval } ; - CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); - return true; - } - @Override - public boolean swapBuffers() { - return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); - } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index af767f0c3..cc727c8e1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -42,10 +42,10 @@ package jogamp.opengl.macosx.cgl; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -92,7 +92,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { this.id = id; } } - private List> createdContexts = new ArrayList>(); + /* pp */ List> createdContexts = new ArrayList>(); private boolean haveSetOpenGLMode = false; private GLBackendType openGLMode = GLBackendType.NSOPENGL; @@ -110,26 +110,42 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0; } - protected void registerContext(MacOSXCGLContext ctx) { + @Override + protected void associateContext(GLContext ctx, boolean bound) { // NOTE: we need to keep track of the created contexts in order to // implement swapBuffers() because of how Mac OS X implements its // OpenGL window interface synchronized (createdContexts) { - createdContexts.add(new WeakReference(ctx)); - } + if(bound) { + createdContexts.add(new WeakReference((MacOSXCGLContext)ctx)); + } else { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext _ctx = ref.get(); + if( _ctx == null || _ctx == ctx) { + createdContexts.remove(i); + } else { + i++; + } + } + } + } } + @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - synchronized (createdContexts) { - for (Iterator> iter = createdContexts.iterator(); iter.hasNext(); ) { - WeakReference ref = iter.next(); - MacOSXCGLContext ctx = ref.get(); - if (ctx != null) { - ctx.swapBuffers(); - } else { - iter.remove(); - } + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + synchronized (createdContexts) { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext ctx = ref.get(); + if (ctx != null) { + ctx.swapBuffers(); + i++; + } else { + createdContexts.remove(i); + } + } } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 591fafc68..e174d38f4 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -51,7 +51,7 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -61,7 +61,8 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.macosx.OSXDummyUpstreamSurfaceHook; import jogamp.opengl.DesktopGLDynamicLookupHelper; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; @@ -71,7 +72,7 @@ import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.nativewindow.WrappedSurface; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.opengl.GLExtensions; @@ -320,9 +321,14 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!caps.isPBuffer()) { + // Actual implementation is using PBuffer ... + final GLCapabilities modCaps = (GLCapabilities) caps.cloneMutable(); + modCaps.setPBuffer(true); + modCaps.setBitmap(false); + config.setChosenCapabilities(modCaps); return new MacOSXOffscreenCGLDrawable(this, target); } return new MacOSXPbufferCGLDrawable(this, target); @@ -336,7 +342,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final MacOSXGraphicsDevice device; if(createNewDevice) { device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); @@ -348,68 +354,23 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); - return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, + new OSXDummyUpstreamSurfaceHook(width, height)); } - private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { - long nsWindow = 0; - @Override - public final void create(ProxySurface s) { - if(0 == nsWindow && 0 == s.getSurfaceHandle()) { - nsWindow = OSXUtil.CreateNSWindow(0, 0, s.getWidth(), s.getHeight()); - if(0 == nsWindow) { - throw new GLException("Error NS window 0"); - } - long nsView = OSXUtil.GetNSView(nsWindow); - if(0 == nsView) { - throw new GLException("Error NS view 0"); - } - s.setSurfaceHandle(nsView); - s.setImplBitfield(ProxySurface.INVISIBLE_WINDOW); - if(DEBUG) { - System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); - } - } - } - @Override - public final void destroy(ProxySurface s) { - if(0 != nsWindow && 0 != s.getSurfaceHandle()) { - OSXUtil.DestroyNSWindow(nsWindow); - nsWindow = 0; - s.setSurfaceHandle(0); - if(DEBUG) { - System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s); - } - } - } - @Override - public final int getWidth(ProxySurface s) { - return s.initialWidth; - } - @Override - public final int getHeight(ProxySurface s) { - return s.initialHeight; - } - - @Override - public String toString() { - return "MacOSXLSurfaceLifecycleHook[]"; - } - - }; @Override protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true); - return new WrappedSurface(config, windowHandle, 0, 0, upstream); + return new WrappedSurface(config, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java index 149927160..8866c7ce6 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -51,23 +51,16 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.MutableGraphicsConfiguration; public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { - long pixelformat; MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen, - GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - long pixelformat) { + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested) { super(screen, capsChosen, capsRequested); - this.pixelformat=pixelformat; } public Object clone() { return super.clone(); } - void setChosenPixelFormat(long pixelformat) { - this.pixelformat=pixelformat; - } - protected static List getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) { MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device); if(null == sharedResource) { @@ -114,11 +107,11 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration break; case CGL.kCGLPFAColorFloat: - ivalues[idx] = caps.getPbufferFloatingPointBuffers() ? 1 : 0; + ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0; break; case CGL.NSOpenGLPFAPixelBuffer: - ivalues[idx] = caps.isPBuffer() ? 1 : 0; + ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() ) ? 1 : 0; break; case CGL.NSOpenGLPFADoubleBuffer: @@ -188,11 +181,11 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration attrs[i++] = CGL.kCGLPFAOpenGLProfile; attrs[i++] = MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor); } - if(caps.isPBuffer()) { + if(!caps.isOnscreen() && caps.isPBuffer()) { attrs[i++] = CGL.kCGLPFAPBuffer; - } - if (caps.getPbufferFloatingPointBuffers()) { - attrs[i++] = CGL.kCGLPFAColorFloat; + if (caps.getPbufferFloatingPointBuffers()) { + attrs[i++] = CGL.kCGLPFAColorFloat; + } } if (caps.getDoubleBuffered()) { attrs[i++] = CGL.kCGLPFADoubleBuffer; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index 13faf7090..43a9d0d1a 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -96,6 +96,6 @@ public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurati capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(device) ); - return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, 0); + return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested); } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 6be9e386d..65ed5fc15 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -49,8 +49,8 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -62,7 +62,6 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) { super(drawable, null); setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); - drawable.registerContext(this); this.contextHandle = handle; GLContextShareSet.contextCreated(this); setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); @@ -108,13 +107,13 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { } AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX); - MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps, pixelFormat); + MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps); if(0 == currentDrawable) { // set a fake marker stating a valid drawable currentDrawable = 1; } - WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, null); + WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, true); return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java index b1e283ebc..ec9628004 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java @@ -52,9 +52,7 @@ public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable { @Override public GLContext createContext(GLContext shareWith) { - final MacOSXOnscreenCGLContext ctx= new MacOSXOnscreenCGLContext(this, shareWith); - registerContext(ctx); - return ctx; + return new MacOSXOnscreenCGLContext(this, shareWith); } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java index 88886ddd2..7e2d8cf10 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -39,6 +39,7 @@ import javax.media.opengl.GLPbuffer; import jogamp.opengl.GLContextImpl; +@SuppressWarnings("deprecation") public class MacOSXPbufferCGLContext extends MacOSXCGLContext { // State for render-to-texture and render-to-texture-rectangle support diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index 8f2f386af..668e463a2 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -40,6 +40,8 @@ package jogamp.opengl.macosx.cgl; +import java.lang.ref.WeakReference; + import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.MutableSurface; @@ -70,9 +72,6 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { // private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV // private int texture; // actual texture object - // Note that we can not store this in the NativeSurface because the - // semantic is that contains an NSView - protected long pBuffer; protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight; public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target) { @@ -90,9 +89,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { @Override public GLContext createContext(GLContext shareWith) { - final MacOSXPbufferCGLContext ctx = new MacOSXPbufferCGLContext(this, shareWith); - registerContext(ctx); - return ctx; + return new MacOSXPbufferCGLContext(this, shareWith); } @Override @@ -101,27 +98,34 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { return 0; } - @Override - public long getHandle() { - return pBuffer; - } - protected int getTextureTarget() { return pBufferTexTarget; } protected int getTextureWidth() { return pBufferTexWidth; } protected int getTextureHeight() { return pBufferTexHeight; } protected void destroyPbuffer() { - if (this.pBuffer != 0) { - NativeSurface ns = getNativeSurface(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final long pBuffer = ms.getSurfaceHandle(); + if (0 != pBuffer) { + synchronized (createdContexts) { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext ctx = ref.get(); + if (ctx != null) { + ctx.detachPBuffer(); + i++; + } else { + createdContexts.remove(i); + } + } + } impl.destroy(pBuffer); - this.pBuffer = 0; - ((MutableSurface)ns).setSurfaceHandle(0); + ms.setSurfaceHandle(0); } } private void createPbuffer() { - final NativeSurface ns = getNativeSurface(); - final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ms.getGraphicsConfiguration(); final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); final GLProfile glProfile = capabilities.getGLProfile(); MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice()); @@ -161,7 +165,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { } } - pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight()); + final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight()); if(DEBUG) { System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+ ", pbufferSize "+getWidth()+"x"+getHeight()+ @@ -174,7 +178,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); } - ((MutableSurface)ns).setSurfaceHandle(pBuffer); + ms.setSurfaceHandle(pBuffer); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 96c1187d3..f6cc2956d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -50,8 +50,8 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextShareSet; @@ -102,7 +102,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println("WindowsExternalWGLContext valid hdc/pfd, retrieved cfg: " + cfg); } } - return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)), ctx, cfg); + return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)), ctx, cfg); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java index 15bd005dc..f8c237c9e 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java @@ -49,10 +49,10 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.GDIUtil; -import com.jogamp.nativewindow.WrappedSurface; public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { @@ -72,7 +72,7 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true); - return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)); + return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java index ca7886e7f..3b3f0c123 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java @@ -73,27 +73,28 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl { } @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - final long t0; - if (PROFILING) { - t0 = System.currentTimeMillis(); - } else { - t0 = 0; - } - - if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { - throw new GLException("Error swapping buffers"); - } - - if (PROFILING) { - profilingSwapBuffersTime += System.currentTimeMillis() - t0; - if (++profilingSwapBuffersTicks == PROFILING_TICKS) { - System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" + - ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)"); - profilingSwapBuffersTime = 0; - profilingSwapBuffersTicks = 0; - } + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + final long t0; + if (PROFILING) { + t0 = System.currentTimeMillis(); + } else { + t0 = 0; + } + + if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { + throw new GLException("Error swapping buffers"); + } + + if (PROFILING) { + profilingSwapBuffersTime += System.currentTimeMillis() - t0; + if (++profilingSwapBuffersTicks == PROFILING_TICKS) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" + + ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)"); + profilingSwapBuffersTime = 0; + profilingSwapBuffersTicks = 0; + } + } } } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 7ea487523..91d5c225a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -52,7 +52,7 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -62,9 +62,10 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook; import jogamp.nativewindow.windows.GDISurface; -import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.windows.RegisteredClassFactory; import jogamp.opengl.DesktopGLDynamicLookupHelper; import jogamp.opengl.GLContextImpl; @@ -79,7 +80,6 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.VersionNumber; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.opengl.GLExtensions; @@ -541,7 +541,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final WindowsGraphicsDevice device; if(createNewDevice) { device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); @@ -553,7 +553,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override @@ -571,57 +571,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+requestedCaps+" on "+screen); } - return new GDISurface(config, 0, width, height, dummySurfaceLifecycleHook); - } - private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { - final GDISurface ms = (GDISurface)s; - if(0 == ms.getWindowHandle()) { - final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, s.getWidth(), s.getHeight()); - if(0 == windowHandle) { - throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError()); - } - ms.setWindowHandle(windowHandle); - if(DEBUG) { - System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.create: "+ms); - } - } - } - @Override - public final void destroy(ProxySurface s) { - final GDISurface ms = (GDISurface)s; - if(0 != ms.getWindowHandle()) { - GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE); - GDIUtil.DestroyDummyWindow(ms.getWindowHandle()); - ms.setWindowHandle(0); - if(DEBUG) { - System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+ms); - } - } - } - @Override - public final int getWidth(ProxySurface s) { - return s.initialWidth; - } - @Override - public final int getHeight(ProxySurface s) { - return s.initialHeight; - } - - @Override - public String toString() { - return "GDISurfaceLifecycleHook[]"; - } - }; - + return new GDISurface(config, 0, new GDIDummyUpstreamSurfaceHook(width, height), createNewDevice); + } @Override protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); - return new GDISurface(cfg, windowHandle, 0, 0, upstream); + return new GDISurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 4d1069e6b..058f4e336 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -107,7 +107,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio if(hasARB) { caps = wglARBPFID2GLCapabilities(sharedResource, device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } else { - caps = PFD2GLCapabilities(glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); + caps = PFD2GLCapabilities(device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } if(null==caps) { throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+ @@ -325,7 +325,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError()); } - return AttribList2GLCapabilities(glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits); + return AttribList2GLCapabilities(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits); } static int[] wglChoosePixelFormatARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, @@ -390,7 +390,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio for(int i = 0; i= 1 && ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { - final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); + final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); if(null != caps) { bucket.add(caps); if(DEBUG) { @@ -398,7 +398,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> "+j+"]: "+caps); } } else if(DEBUG) { - GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS); + GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS); System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> skip]: pfdID "+pfdIDs[i]+", "+skipped+", winattr "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); } } else if (DEBUG) { @@ -616,9 +616,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio return val; } - static WGLGLCapabilities AttribList2GLCapabilities(final GLProfile glp, - final long hdc, final int pfdID, final int[] iattribs, - final int niattribs, final int[] iresults, final int winattrmask) { + static WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device, + final GLProfile glp, final long hdc, final int pfdID, + final int[] iattribs, final int niattribs, final int[] iresults, final int winattrmask) { final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults); int drawableTypeBits = winattrmask & allDrawableTypeBits; @@ -637,7 +637,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByARB(iattribs, niattribs, iresults); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } // @@ -672,7 +672,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio return val; } - static WGLGLCapabilities PFD2GLCapabilities(final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { + static WGLGLCapabilities PFD2GLCapabilities(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); if(null == pfd) { return null; @@ -689,21 +689,22 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits ); + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } - static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(final GLProfile glp, final long hdc, final int pfdID) { + static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); - return PFD2GLCapabilitiesNoCheck(glp, pfd, pfdID); + return PFD2GLCapabilitiesNoCheck(device, glp, pfd, pfdID); } - static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) { + static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) { if(null == pfd) { return null; } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, PFD2DrawableTypeBits(pfd)); + + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res); } static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 41c9bba02..d2d1dafc8 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -113,13 +113,14 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } protected static List getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) { - WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); + final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); if(null == sharedResource) { throw new GLException("Shared resource for device n/a: "+device); } - GLDrawableImpl sharedDrawable = sharedResource.getDrawable(); - GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - GLContext sharedContext = sharedResource.getContext(); + final GLDrawableImpl sharedDrawable = sharedResource.getDrawable(); + final GLContext sharedContext = sharedResource.getContext(); + final GLProfile glp = GLProfile.getDefault(device); + List availableCaps = null; if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -135,10 +136,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat throw new GLException("Error: HDC is null"); } if (sharedResource.hasARBPixelFormat()) { - availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), capsChosen.getGLProfile(), hdc); + availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc); } if( null == availableCaps || availableCaps.isEmpty() ) { - availableCaps = getAvailableGLCapabilitiesGDI(device, capsChosen.getGLProfile(), hdc); + availableCaps = getAvailableGLCapabilitiesGDI(device, glp, hdc); } } finally { if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -165,7 +166,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat int numFormats = pformats.length; List bucket = new ArrayList(numFormats); for (int i = 0; i < numFormats; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); + final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); if(null != caps) { bucket.add(caps); } @@ -439,7 +440,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat private static boolean updateGraphicsConfigurationGDI(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, long hdc, boolean extHDC, int[] pformats) { GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - if(capsChosen.isPBuffer()) { + if( !capsChosen.isOnscreen() && capsChosen.isPBuffer() ) { if (DEBUG) { System.err.println("updateGraphicsConfigurationGDI: no pbuffer supported on GDI: " + capsChosen); } @@ -454,6 +455,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat System.err.println("updateGraphicsConfigurationGDI: capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString()); } + AbstractGraphicsDevice device = config.getScreen().getDevice(); int pfdID; // chosen or preset PFD ID WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] @@ -468,7 +470,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat + ", pixelformat " + pfdID); } pixelFormatSet = true; - pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, winattrmask); + pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask); if(null == pixelFormatCaps) { throw new GLException("Could not map PFD2GLCaps w/ already chosen pfdID "+pfdID); } @@ -480,7 +482,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat List availableCaps = new ArrayList(); for (int i = 0; i < pformats.length; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], winattrmask); + final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask); if(null != caps) { availableCaps.add(caps); if(DEBUG) { @@ -488,7 +490,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> "+j+"]: "+caps); } } else if(DEBUG) { - GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(glProfile, hdc, pformats[i]); + GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, hdc, pformats[i]); System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> skip]: pfdID "+pformats[i]+", "+skipped); } } @@ -505,8 +507,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat recommendedIndex--) { /* nop */ } if(DEBUG && 0 > recommendedIndex) { - final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(glProfile, pfd, pfdID); - final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, winattrmask); + final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, pfd, pfdID); + final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask); System.err.println("Chosen PFDID "+pfdID+", but not found in available caps (use given pfdIDs "+givenPFormats+", reqPFDCaps "+reqPFDCaps+", chosenCaps: "+chosenCaps); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index 1f3edbd8a..03a0eefbf 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -48,10 +48,10 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11ExternalGLXContext extends X11GLXContext { @@ -105,7 +105,7 @@ public class X11ExternalGLXContext extends X11GLXContext { cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); } - final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, null); + final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, true); return new X11ExternalGLXContext(new Drawable(factory, ns), ctx); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java index 8652e2d4a..ac78c6f4a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java @@ -45,7 +45,8 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; + import com.jogamp.nativewindow.x11.X11GraphicsScreen; @@ -87,7 +88,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable { System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")"); } } - return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, null)); + return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, true)); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java index e9912ce9d..8c642777d 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java @@ -69,9 +69,10 @@ public abstract class X11GLXDrawable extends GLDrawableImpl { } @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); + } } //--------------------------------------------------------------------------- diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index bc3e5b793..fb11f8bba 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -49,7 +49,7 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -59,6 +59,8 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.x11.X11DummyUpstreamSurfaceHook; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -70,7 +72,6 @@ import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.util.VersionNumber; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; @@ -505,7 +506,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final X11GraphicsDevice device; if(createNewDevice) { // Null X11 locking, due to private non-shared Display handle @@ -518,65 +519,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface( config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); - return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new X11DummyUpstreamSurfaceHook(width, height)); } - private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { - if( 0 == s.getSurfaceHandle() ) { - final X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration(); - final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen(); - final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); - if(0 == device.getHandle()) { - device.open(); - s.setImplBitfield(ProxySurface.OWN_DEVICE); - } - final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), s.getWidth(), s.getHeight()); - if(0 == windowHandle) { - throw new GLException("Creating dummy window failed w/ "+cfg+", "+s.getWidth()+"x"+s.getHeight()); - } - s.setSurfaceHandle(windowHandle); - if(DEBUG) { - System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.create: "+s); - } - } - } - @Override - public final void destroy(ProxySurface s) { - if(0 != s.getSurfaceHandle()) { - final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration(); - final X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice(); - X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle()); - s.setSurfaceHandle(0); - if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { - device.close(); - } - if(DEBUG) { - System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s); - } - } - } - @Override - public final int getWidth(ProxySurface s) { - return s.initialWidth; - } - @Override - public final int getHeight(ProxySurface s) { - return s.initialHeight; - } - @Override - public String toString() { - return "X11SurfaceLifecycleHook[]"; - } - }; - @Override protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { @@ -593,7 +544,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if(DEBUG) { System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg); } - return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); + return new WrappedSurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index 866fcbbe4..96c3c4123 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -307,7 +307,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return null; // no RGBA -> color index not supported } - X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); + final X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); if (isMultisampleAvailable) { res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); @@ -342,7 +342,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); } catch (Exception e) {} - return (X11GLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } private static String glXGetFBConfigErrorCode(int err) { @@ -462,7 +462,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); - return (X11GLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } private static String glXGetConfigErrorCode(int err) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 8086cd26a..431706e24 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -129,9 +129,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen(); final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(sharedScreen.getDevice()); - final X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable(); - final GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - final GLProfile glp = capsChosen.getGLProfile(); + final GLProfile glp = GLProfile.getDefault(device); List availableCaps = null; @@ -217,7 +215,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) ); - boolean usePBuffer = capsChosen.isPBuffer(); + boolean usePBuffer = !capsChosen.isOnscreen() && capsChosen.isPBuffer(); X11GLXGraphicsConfiguration res = null; if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java index e1fe2f27e..bba2b3513 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java @@ -81,10 +81,11 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } private void createPbuffer() { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration(); - AbstractGraphicsScreen aScreen = config.getScreen(); - AbstractGraphicsDevice aDevice = aScreen.getDevice(); - long display = aDevice.getHandle(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ms.getGraphicsConfiguration(); + final AbstractGraphicsScreen aScreen = config.getScreen(); + final AbstractGraphicsDevice aDevice = aScreen.getDevice(); + final long display = aDevice.getHandle(); if (DEBUG) { System.out.println("Pbuffer config: " + config); @@ -94,8 +95,6 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { throw new GLException("Null display"); } - NativeSurface ns = getNativeSurface(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); if (chosenCaps.getPbufferRenderToTexture()) { @@ -111,9 +110,9 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { int[] iattributes = new int[7]; iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH; - iattributes[niattribs++] = ns.getWidth(); + iattributes[niattribs++] = ms.getWidth(); iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT; - iattributes[niattribs++] = ns.getHeight(); + iattributes[niattribs++] = ms.getHeight(); iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact iattributes[niattribs++] = 0; iattributes[niattribs++] = 0; @@ -125,7 +124,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } // Set up instance variables - ((MutableSurface)ns).setSurfaceHandle(pbuffer); + ms.setSurfaceHandle(pbuffer); if (DEBUG) { System.err.println("Created pbuffer " + this); diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m new file mode 100644 index 000000000..63323b76d --- /dev/null +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -0,0 +1,665 @@ +#import "MacOSXWindowSystemInterface.h" +#import +#import +#include "timespec.h" + +// +// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. +// Use CVDisplayLink otherwise. +// +// #define HAS_CADisplayLink 1 +// + +// lock/sync debug output +// +// #define DBG_SYNC 1 +// +#ifdef DBG_SYNC + // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define SYNC_PRINT(...) +#endif + +// fps debug output +// +// #define DBG_PERF 1 + +@interface MyNSOpenGLLayer: NSOpenGLLayer +{ +@private + GLfloat gl_texCoords[8]; + +@protected + NSOpenGLContext* parentCtx; + NSOpenGLPixelFormat* parentPixelFmt; + volatile NSOpenGLPixelBuffer* pbuffer; + volatile GLuint textureID; + volatile int texWidth; + volatile int texHeight; +#ifdef HAS_CADisplayLink + CADisplayLink* displayLink; +#else + CVDisplayLinkRef displayLink; +#endif + int tc; + struct timespec tStart; +@public + struct timespec lastWaitTime; + GLint swapInterval; + GLint swapIntervalCounter; + pthread_mutex_t renderLock; + pthread_cond_t renderSignal; + volatile Bool shallDraw; + volatile int newTexWidth; + volatile int newTexHeight; +} + +- (id) setupWithContext: (NSOpenGLContext*) parentCtx + pixelFormat: (NSOpenGLPixelFormat*) pfmt + pbuffer: (NSOpenGLPixelBuffer*) p + texIDArg: (GLuint) texID + opaque: (Bool) opaque + texWidth: (int) texWidth + texHeight: (int) texHeight; + +- (Bool) validateTexSizeWithNewSize; +- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight; +- (void) setTextureID: (int) _texID; + +- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p; + +- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat; +- (void)disableAnimation; +- (void)pauseAnimation:(Bool)pause; +- (void)deallocPBuffer; +- (void)releaseLayer; +- (void)dealloc; +- (void)setSwapInterval:(int)interval; +- (void)tick; +- (void)waitUntilRenderSignal: (long) to_micros; +- (Bool)isGLSourceValid; + +@end + +#ifndef HAS_CADisplayLink + +static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; + pthread_mutex_lock(&l->renderLock); + if( 0 < l->swapInterval ) { + l->swapIntervalCounter++; + if( l->swapIntervalCounter >= l->swapInterval ) { + SYNC_PRINT("", (int)l->swapIntervalCounter, l->swapInterval); + l->swapIntervalCounter = 0; + pthread_cond_signal(&l->renderSignal); // wake up vsync + } + } + pthread_mutex_unlock(&l->renderLock); + [pool release]; + return kCVReturnSuccess; +} + +#endif + +static const GLfloat gl_verts[] = { + -1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0, + 1.0, -1.0 +}; + +@implementation MyNSOpenGLLayer + +- (id) setupWithContext: (NSOpenGLContext*) _parentCtx + pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt + pbuffer: (NSOpenGLPixelBuffer*) p + texIDArg: (GLuint) texID + opaque: (Bool) opaque + texWidth: (int) _texWidth + texHeight: (int) _texHeight; +{ + pthread_mutexattr_t renderLockAttr; + pthread_mutexattr_init(&renderLockAttr); + pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&renderLock, &renderLockAttr); // recursive + pthread_cond_init(&renderSignal, NULL); // no attribute + + { + int i; + for(i=0; i<8; i++) { + gl_texCoords[i] = 0.0f; + } + } + parentCtx = _parentCtx; + parentPixelFmt = _parentPixelFmt; + swapInterval = 1; // defaults to on (as w/ new GL profiles) + swapIntervalCounter = 0; + timespec_now(&lastWaitTime); + shallDraw = NO; + newTexWidth = _texWidth; + newTexHeight = _texHeight; + [self validateTexSizeWithNewSize]; + [self setTextureID: texID]; + + pbuffer = p; + if(NULL != pbuffer) { + [pbuffer retain]; + } + + { + // no animations for add/remove/swap sublayers etc + // doesn't work: [self removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] + [self removeAllAnimations]; + } + + // instantiate a deactivated displayLink +#ifdef HAS_CADisplayLink + displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; +#else + CVReturn cvres; + { + int allDisplaysMask = 0; + int virtualScreen, accelerated, displayMask; + for (virtualScreen = 0; virtualScreen < [parentPixelFmt numberOfVirtualScreens]; virtualScreen++) { + [parentPixelFmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; + [parentPixelFmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; + if (accelerated) { + allDisplaysMask |= displayMask; + } + } + cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [parentCtx CGLContextObj], [parentPixelFmt CGLPixelFormatObj]); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); + displayLink = NULL; + } + } +#endif + [self pauseAnimation: YES]; + + [self removeAllAnimations]; + [self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [self setNeedsDisplayOnBoundsChange: YES]; + + [self setOpaque: opaque ? YES : NO]; + + if(NULL != pbuffer) { + DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n", + self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, + lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); + } else { + DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n", + self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight, + lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); + } + return self; +} + +- (Bool) validateTexSizeWithNewSize +{ + return [self validateTexSize: newTexWidth texHeight: newTexHeight]; +} + +- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight +{ + if(_texHeight != texHeight || _texWidth != texWidth) { + texWidth = _texWidth; + texHeight = _texHeight; + CGRect lRect = [self bounds]; + lRect.origin.x = 0; + lRect.origin.y = 0; + lRect.size.width = texWidth; + lRect.size.height = texHeight; + [self setFrame: lRect]; + + GLfloat texCoordWidth, texCoordHeight; + if(NULL != pbuffer) { + GLenum textureTarget = [pbuffer textureTarget] ; + GLsizei pwidth = [pbuffer pixelsWide]; + GLsizei pheight = [pbuffer pixelsHigh]; + if( GL_TEXTURE_2D == textureTarget ) { + texCoordWidth = (GLfloat)pwidth /(GLfloat)texWidth ; + texCoordHeight = (GLfloat)pheight/(GLfloat)texHeight ; + } else { + texCoordWidth = pwidth; + texCoordHeight = pheight; + } + } else { + texCoordWidth = (GLfloat)1.0f; + texCoordHeight = (GLfloat)1.0f; + } + gl_texCoords[3] = texCoordHeight; + gl_texCoords[5] = texCoordHeight; + gl_texCoords[4] = texCoordWidth; + gl_texCoords[6] = texCoordWidth; + return YES; + } else { + return NO; + } +} + +- (void) setTextureID: (int) _texID +{ + textureID = _texID; +} + +- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p +{ + if( pbuffer != p ) { + DBG_PRINT("MyNSOpenGLLayer::validatePBuffer.0 %p, pbuffer %p, (refcnt %d)\n", self, p, (int)[self retainCount]); + + SYNC_PRINT("{PB-nil}"); + + [self deallocPBuffer]; + + pbuffer = p; + if(NULL != pbuffer) { + [pbuffer retain]; + } + [self setTextureID: 0]; + + shallDraw = NO; + } +} + +/** +- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask +{ + DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n", + self, (int)[self retainCount], parentPixelFmt, parentPixelFmt); + return parentPixelFmt; +} */ + +- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat +{ + NSOpenGLContext * nctx = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:parentCtx]; + DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat: %p (refcnt %d) - pfmt %p, parent %p -> new-ctx %p\n", + self, (int)[self retainCount], pixelFormat, parentCtx, nctx); + return nctx; +} + +- (void)disableAnimation +{ + DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink); + pthread_mutex_lock(&renderLock); + [self setAsynchronous: NO]; + if(NULL != displayLink) { +#ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + [displayLink release]; +#else + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); +#endif + displayLink = NULL; + } + pthread_mutex_unlock(&renderLock); +} + +- (void)deallocPBuffer +{ + if(NULL != pbuffer) { + NSOpenGLContext* context = [self openGLContext]; + if(NULL!=context) { + [context makeCurrentContext]; + + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)texureID); + + if( 0 != textureID ) { + glDeleteTextures(1, &textureID); + } + [pbuffer release]; + + [context clearDrawable]; + } else { + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)texureID); + } + pbuffer = NULL; + [self setTextureID: 0]; + } +} + +- (void)releaseLayer +{ + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_lock(&renderLock); + [self disableAnimation]; + [self deallocPBuffer]; + [self release]; + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_unlock(&renderLock); +} + +- (void)dealloc +{ + DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); + // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]); + + pthread_mutex_lock(&renderLock); + [self disableAnimation]; + [self deallocPBuffer]; + pthread_mutex_unlock(&renderLock); + pthread_cond_destroy(&renderSignal); + pthread_mutex_destroy(&renderLock); + [super dealloc]; + DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self); +} + +- (Bool)isGLSourceValid +{ + return NULL != pbuffer || 0 != textureID ; +} + +- (void)resizeWithOldSuperlayerSize:(CGSize)size + { + CGRect lRectS = [[self superlayer] bounds]; + + DBG_PRINT("MyNSOpenGLLayer::resizeWithOldSuperlayerSize: %p, texSize %dx%d, bounds: %lfx%lf -> %lfx%lf (refcnt %d)\n", + self, texWidth, texHeight, size.width, size.height, lRectS.size.width, lRectS.size.height, (int)[self retainCount]); + + newTexWidth = lRectS.size.width; + newTexHeight = lRectS.size.height; + shallDraw = YES; + SYNC_PRINT("", newTexWidth, newTexHeight); + + [super resizeWithOldSuperlayerSize: size]; +} + +- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + SYNC_PRINT("", (int)shallDraw); + return shallDraw; +} + +- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + pthread_mutex_unlock(&renderLock); + SYNC_PRINT("<* "); + // NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]); + + if( shallDraw && ( NULL != pbuffer || 0 != textureID ) ) { + [context makeCurrentContext]; + + GLenum textureTarget; + + Bool texSizeChanged = [self validateTexSizeWithNewSize]; + + if( NULL != pbuffer ) { + if( texSizeChanged && 0 != textureID ) { + glDeleteTextures(1, &textureID); + [self setTextureID: 0]; + } + textureTarget = [pbuffer textureTarget]; + if( 0 == textureID ) { + glGenTextures(1, &textureID); + glBindTexture(textureTarget, textureID); + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } else { + glBindTexture(textureTarget, textureID); + } + [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; + } else { + textureTarget = GL_TEXTURE_2D; + glBindTexture(textureTarget, textureID); + } + SYNC_PRINT(" %d*>", (int)textureID); + + glEnable(textureTarget); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, gl_verts); + glTexCoordPointer(2, GL_FLOAT, 0, gl_texCoords); + + glDrawArrays(GL_QUADS, 0, 4); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(textureTarget); + glBindTexture(textureTarget, 0); + + [context clearDrawable]; + + [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; + + } else { + // glClear(GL_COLOR_BUFFER_BIT); + // glBlitFramebuffer(0, 0, texWidth, texHeight, + // 0, 0, texWidth, texHeight, + // GL_COLOR_BUFFER_BIT, GL_NEAREST); + SYNC_PRINT(" 0*>"); + } + + #ifdef DBG_PERF + [self tick]; + #endif + shallDraw = NO; + + if( 0 >= swapInterval ) { + pthread_cond_signal(&renderSignal); // wake up !vsync + SYNC_PRINT(""); + } + SYNC_PRINT("<$>\n"); + pthread_mutex_unlock(&renderLock); +} + +- (void)pauseAnimation:(Bool)pause +{ + DBG_PRINT("MyNSOpenGLLayer::pauseAnimation: %d\n", (int)pause); + [self setAsynchronous: NO]; + if(pause) { + if(NULL != displayLink) { + #ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + #else + CVDisplayLinkStop(displayLink); + #endif + } + } else { + if(NULL != displayLink) { + #ifdef HAS_CADisplayLink + [displayLink setPaused: NO]; + [displayLink setFrameInterval: swapInterval]; + #else + CVDisplayLinkStart(displayLink); + #endif + } + } + tc = 0; + timespec_now(&tStart); +} + +- (void)setSwapInterval:(int)interval +{ + /** + * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( + * Using CVDisplayLink .. see setSwapInterval() below. + * + GLint si; + [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; + if(si != swapInterval) { + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); + [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + } + */ + + pthread_mutex_lock(&renderLock); + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0: %d - displayLink %p\n", interval, displayLink); + swapInterval = interval; + swapIntervalCounter = 0; + pthread_mutex_unlock(&renderLock); + + if(0 < swapInterval) { + [self pauseAnimation: NO]; + } else { + [self pauseAnimation: YES]; + } + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.X: %d\n", interval); +} + +-(void)tick +{ + tc++; + if(tc%60==0) { + struct timespec t1, td; + timespec_now(&t1); + timespec_subtract(&td, &t1, &tStart); + long td_ms = timespec_milliseconds(&td); + fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", + td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); + fflush(NULL); + } +} + +- (void)waitUntilRenderSignal: (long) to_micros +{ + BOOL ready = NO; + int wr = 0; + pthread_mutex_lock(&renderLock); + SYNC_PRINT("{W %ld us", to_micros); + do { + if(0 >= swapInterval) { + ready = YES; + } + if(NO == ready) { + #ifdef DBG_SYNC + struct timespec t0, t1, td, td2; + timespec_now(&t0); + #endif + if(0 < to_micros) { + struct timespec to_abs = lastWaitTime; + timespec_addmicros(&to_abs, to_micros); + #ifdef DBG_SYNC + timespec_subtract(&td, &to_abs, &t0); + fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td)); + #endif + wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs); + #ifdef DBG_SYNC + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + timespec_subtract(&td2, &t1, &lastWaitTime); + fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); + #endif + } else { + pthread_cond_wait (&renderSignal, &renderLock); + #ifdef DBG_SYNC + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + timespec_subtract(&td2, &t1, &lastWaitTime); + fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); + #endif + } + ready = YES; + } + } while (NO == ready && 0 == wr) ; + SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready); + timespec_now(&lastWaitTime); + pthread_mutex_unlock(&renderLock); +} + +@end + +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) { + // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? + // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. + // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID + // opaque: opaque texWidth: texWidth texHeight: texHeight]; + + return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID + opaque: opaque texWidth: texWidth texHeight: texHeight]; +} + +void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [l setSwapInterval: interval]; + [pool release]; +} + +void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [l waitUntilRenderSignal: to_micros]; + [pool release]; +} + +void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + pthread_mutex_lock(&l->renderLock); + [l validatePBuffer:0]; + pthread_mutex_unlock(&l->renderLock); + + [pool release]; +} + +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + Bool shallDraw; + + pthread_mutex_lock(&l->renderLock); + [l validatePBuffer:p]; + // l->newTexWidth = texWidth; + // l->newTexHeight = texHeight; + [l setTextureID: texID]; + shallDraw = [l isGLSourceValid]; + l->shallDraw = shallDraw; + pthread_mutex_unlock(&l->renderLock); + + SYNC_PRINT("", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); + if(shallDraw) { + if ( [NSThread isMainThread] == YES ) { + [l setNeedsDisplay]; + } else { + // don't wait - using doublebuffering + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + } + } + // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); + [pool release]; +} + +void releaseNSOpenGLLayer(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l); + + if ( [NSThread isMainThread] == YES ) { + [l releaseLayer]; + } else { + [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO]; + } + + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l); + [pool release]; +} + diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m deleted file mode 100644 index b81b43e54..000000000 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m +++ /dev/null @@ -1,494 +0,0 @@ -#import "MacOSXWindowSystemInterface.h" -#import -#import -#include "timespec.h" - -// -// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. -// Use CVDisplayLink otherwise. -// -// #define HAS_CADisplayLink 1 -// - -// lock/sync debug output -// -// #define DBG_SYNC 1 -// -#ifdef DBG_SYNC - // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) - #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#else - #define SYNC_PRINT(...) -#endif - -// fps debug output -// -// #define DBG_PERF 1 - -@interface MyNSOpenGLLayer: NSOpenGLLayer -{ -@protected - NSOpenGLPixelBuffer* pbuffer; - int texWidth; - int texHeight; - GLuint textureID; -#ifdef HAS_CADisplayLink - CADisplayLink* displayLink; -#else - CVDisplayLinkRef displayLink; -#endif - int tc; - struct timespec t0; -@public - struct timespec lastWaitTime; - GLint swapInterval; - GLint swapIntervalCounter; - pthread_mutex_t renderLock; - pthread_cond_t renderSignal; - BOOL shallDraw; -} - -- (id) setupWithContext: (NSOpenGLContext*) ctx - pixelFormat: (NSOpenGLPixelFormat*) pfmt - pbuffer: (NSOpenGLPixelBuffer*) p - opaque: (Bool) opaque - texWidth: (int) texWidth - texHeight: (int) texHeight; - -- (void)deallocTex; -- (void)disableAnimation; -- (void)releaseLayer; -- (void)dealloc; -- (int)getSwapInterval; -- (void)setSwapInterval:(int)interval; -- (void)tick; - -@end - -#ifndef HAS_CADisplayLink - -static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, - const CVTimeStamp *inNow, - const CVTimeStamp *inOutputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *displayLinkContext) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; - pthread_mutex_lock(&l->renderLock); - #ifdef DBG_PERF - [l tick]; - #endif - if(0 < l->swapInterval) { - l->swapIntervalCounter++; - if(l->swapIntervalCounter>=l->swapInterval) { - l->swapIntervalCounter = 0; - pthread_cond_signal(&l->renderSignal); - SYNC_PRINT("S"); - } - } - pthread_mutex_unlock(&l->renderLock); - [pool release]; - return kCVReturnSuccess; -} - -#endif - -@implementation MyNSOpenGLLayer - -- (id) setupWithContext: (NSOpenGLContext*) _ctx - pixelFormat: (NSOpenGLPixelFormat*) _fmt - pbuffer: (NSOpenGLPixelBuffer*) p - opaque: (Bool) opaque - texWidth: (int) _texWidth - texHeight: (int) _texHeight; -{ - pthread_mutexattr_t renderLockAttr; - pthread_mutexattr_init(&renderLockAttr); - pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&renderLock, &renderLockAttr); // recursive - pthread_cond_init(&renderSignal, NULL); // no attribute - - textureID = 0; - swapInterval = 1; // defaults to on (as w/ new GL profiles) - swapIntervalCounter = 0; - timespec_now(&lastWaitTime); - shallDraw = NO; - texWidth = _texWidth; - texHeight = _texHeight; - pbuffer = p; - [pbuffer retain]; - - { - CGRect lRect = CGRectMake(0, 0, texWidth, texHeight); - [self setFrame:lRect]; - - // no animations for add/remove/swap sublayers etc - // doesn't work: [self removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] - [self removeAllAnimations]; - } - - // instantiate a deactivated displayLink -#ifdef HAS_CADisplayLink - displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; - [displayLink setPaused: YES]; -#else - CVReturn cvres; - { - int allDisplaysMask = 0; - int virtualScreen, accelerated, displayMask; - for (virtualScreen = 0; virtualScreen < [_fmt numberOfVirtualScreens]; virtualScreen++) { - [_fmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; - [_fmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; - if (accelerated) { - allDisplaysMask |= displayMask; - } - } - cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [_ctx CGLContextObj], [_fmt CGLPixelFormatObj]); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - CVDisplayLinkStop(displayLink); - } -#endif - [self setAsynchronous: YES]; - - [self setNeedsDisplayOnBoundsChange: YES]; - - [self setOpaque: opaque ? YES : NO]; - - CGRect lRect = [self frame]; - DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, frame: %lf/%lf %lfx%lf (refcnt %d)\n", - self, _ctx, _fmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, - lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); - return self; -} - -- (void)disableAnimation -{ - DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink); - pthread_mutex_lock(&renderLock); - [self setAsynchronous: NO]; - if(NULL != displayLink) { -#ifdef HAS_CADisplayLink - [displayLink setPaused: YES]; - [displayLink release]; -#else - CVDisplayLinkStop(displayLink); - CVDisplayLinkRelease(displayLink); -#endif - displayLink = NULL; - } - pthread_mutex_unlock(&renderLock); -} - -- (void)deallocTex -{ - pthread_mutex_lock(&renderLock); - NSOpenGLContext* context = [self openGLContext]; - DBG_PRINT("MyNSOpenGLLayer::deallocTex %p (refcnt %d) - context %p, pbuffer %p\n", self, (int)[self retainCount], context, pbuffer); - if(NULL != pbuffer) { - if(NULL!=context) { - [context makeCurrentContext]; - if(0 != textureID) { - glDeleteTextures(1, &textureID); - textureID = 0; - } - [context clearDrawable]; - } - [pbuffer release]; - pbuffer = NULL; - } - pthread_mutex_unlock(&renderLock); -} - -- (void)releaseLayer -{ - DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); - pthread_mutex_lock(&renderLock); - [self disableAnimation]; - [self deallocTex]; - [self release]; - DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]); - pthread_mutex_unlock(&renderLock); -} - -- (void)dealloc -{ - DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); - // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]); - - [self disableAnimation]; - [self deallocTex]; - pthread_cond_destroy(&renderSignal); - pthread_mutex_destroy(&renderLock); - [super dealloc]; - DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self); -} - -- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp -{ - // assume both methods 'canDrawInOpenGLContext' and 'drawInOpenGLContext' - // are called from the same thread subsequently - pthread_mutex_lock(&renderLock); - Bool res = NULL != pbuffer && YES == shallDraw; - if(!res) { - SYNC_PRINT("0"); - pthread_mutex_unlock(&renderLock); - } else { - SYNC_PRINT("1"); - } - return res; -} - -- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp -{ - [context makeCurrentContext]; - - GLenum textureTarget = [pbuffer textureTarget]; - GLfloat texCoordWidth, texCoordHeight; - { - GLsizei pwidth = [pbuffer pixelsWide]; - GLsizei pheight = [pbuffer pixelsHigh]; - texCoordWidth = textureTarget == GL_TEXTURE_2D ? (GLfloat)pwidth /(GLfloat)texWidth : pwidth; - texCoordHeight = textureTarget == GL_TEXTURE_2D ? (GLfloat)pheight/(GLfloat)texHeight : pheight; - } - Bool texCreated = 0 == textureID; - - if(texCreated) { - glGenTextures(1, &textureID); - - CGRect lRect = [self frame]; - DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, pbuffer %p %dx%d -> tex %dx%d [%fx%f] id 0x%X target 0x%X, frame: %lf/%lf %lfx%lf (refcnt %d)\n", - self, pbuffer, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, texCoordWidth, texCoordHeight, textureID, textureTarget, - lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); - } - - glBindTexture(textureTarget, textureID); - - /** - if(texCreated) { - // proper tex size setup - glTexImage2D(textureTarget, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - } */ - - [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; - - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glEnable(textureTarget); - - static GLfloat verts[] = { - -1.0, -1.0, - -1.0, 1.0, - 1.0, 1.0, - 1.0, -1.0 - }; - - GLfloat tex[] = { - 0.0, 0.0, - 0.0, texCoordHeight, - texCoordWidth, texCoordHeight, - texCoordWidth, 0.0 - }; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, verts); - glTexCoordPointer(2, GL_FLOAT, 0, tex); - - glDrawArrays(GL_QUADS, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(textureTarget); - glBindTexture(textureTarget, 0); - - [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; - shallDraw = NO; - if(0 >= swapInterval) { - pthread_cond_signal(&renderSignal); // just to wake up - SYNC_PRINT("s"); - } - SYNC_PRINT("$"); - pthread_mutex_unlock(&renderLock); -} - -- (int)getSwapInterval -{ - return swapInterval; -} - -- (void)setSwapInterval:(int)interval -{ - /** - * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( - * Using CVDisplayLink .. see setSwapInterval() below. - * - GLint si; - [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; - if(si != swapInterval) { - DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); - [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; - } - } */ - - pthread_mutex_lock(&renderLock); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0: %d - displayLink %p\n", interval, displayLink); - swapInterval = interval; - swapIntervalCounter = 0; - pthread_mutex_unlock(&renderLock); - - if(NULL!=displayLink) { - if(0 < swapInterval) { - tc = 0; - timespec_now(&t0); - - [self setAsynchronous: NO]; - #ifdef HAS_CADisplayLink - [displayLink setPaused: NO]; - [displayLink setFrameInterval: interval]; - #else - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.1.b.1\n"); - CVDisplayLinkStart(displayLink); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.1.b.X\n"); - #endif - } else { - #ifdef HAS_CADisplayLink - [displayLink setPaused: YES]; - #else - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0.b.1\n"); - CVDisplayLinkStop(displayLink); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0.b.X\n"); - #endif - [self setAsynchronous: YES]; - } - } - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.X: %d\n", interval); -} - --(void)tick -{ - tc++; - if(tc%60==0) { - struct timespec t1, td; - timespec_now(&t1); - timespec_subtract(&td, &t1, &t0); - long td_ms = timespec_milliseconds(&td); - fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", - td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); - fflush(NULL); - } -} - -@end - -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, Bool opaque, int texWidth, int texHeight) { - // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? - // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. - // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; - - return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; -} - -void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - [l setSwapInterval: interval]; -} - -void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - BOOL ready = NO; - int wr = 0; - pthread_mutex_lock(&l->renderLock); - SYNC_PRINT("{"); - do { - if([l getSwapInterval] <= 0) { - ready = !l->shallDraw; - } - if(NO == ready) { - if(0 < to_micros) { - #ifdef DBG_SYNC - struct timespec t0, t1, td, td2; - timespec_now(&t0); - #endif - struct timespec to_abs = l->lastWaitTime; - timespec_addmicros(&to_abs, to_micros); - #ifdef DBG_SYNC - timespec_subtract(&td, &to_abs, &t0); - fprintf(stderr, "(%ld) / ", timespec_milliseconds(&td)); - #endif - wr = pthread_cond_timedwait(&l->renderSignal, &l->renderLock, &to_abs); - #ifdef DBG_SYNC - timespec_now(&t1); - timespec_subtract(&td, &t1, &t0); - timespec_subtract(&td2, &t1, &l->lastWaitTime); - fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); - #endif - } else { - pthread_cond_wait (&l->renderSignal, &l->renderLock); - } - ready = !l->shallDraw; - } - } while (NO == ready && 0 == wr) ; - SYNC_PRINT("-%d}", ready); - timespec_now(&l->lastWaitTime); - pthread_mutex_unlock(&l->renderLock); -} - -void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - pthread_mutex_lock(&l->renderLock); - l->shallDraw = YES; - if ( [NSThread isMainThread] == YES ) { - [l setNeedsDisplay]; - } else { - // can't wait, otherwise we may deadlock AWT - [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; - } - SYNC_PRINT("."); - pthread_mutex_unlock(&l->renderLock); - // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); - [pool release]; -} - -void releaseNSOpenGLLayer(NSOpenGLLayer* layer) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l); - - if ( [NSThread isMainThread] == YES ) { - [l releaseLayer]; - } else { - [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO]; - } - - DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l); - [pool release]; -} - diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m index f774f8f4a..becd41bb2 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m @@ -696,6 +696,11 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* [pool release]; } +Bool isNSOpenGLPixelBuffer(uint64_t object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + return [nsObj isMemberOfClass:[NSOpenGLPixelBuffer class]]; +} + #include Bool imagesInitialized = false; static char libGLStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; @@ -746,38 +751,3 @@ void resetGammaRamp() { CGDisplayRestoreColorSyncSettings(); } -/*** - * The following static functions are copied out of NEWT's OSX impl. - * May need to push code to NativeWindow, to remove duplication. - */ -static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - return (NSScreen *) [screens objectAtIndex: screen_idx]; -} -static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { - // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! - NSDictionary * dict = [screen deviceDescription]; - NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; - // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size - return (CGDirectDisplayID) [val integerValue]; -} -static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) -{ - long value = 0; - CFNumberRef numRef; - numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); - if (numRef != NULL) - CFNumberGetValue(numRef, kCFNumberLongType, &value); - return value; -} -#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) - -int getScreenRefreshRate(int scrn_idx) { - NSScreen *screen = NewtScreen_getNSScreenByIndex(scrn_idx); - CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); - CFDictionaryRef mode = CGDisplayCurrentMode(display); - return CGDDGetModeRefreshRate(mode); -} - diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java new file mode 100644 index 000000000..22c95f3dd --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java @@ -0,0 +1,39 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class DelegatedUpstreamSurfaceHookMutableSize extends UpstreamSurfaceHookMutableSize { + final UpstreamSurfaceHook upstream; + + /** + * @param upstream optional upstream UpstreamSurfaceHook used for {@link #create(ProxySurface)} and {@link #destroy(ProxySurface)}. + * @param width initial width + * @param height initial height + */ + public DelegatedUpstreamSurfaceHookMutableSize(UpstreamSurfaceHook upstream, int width, int height) { + super(width, height); + this.upstream = upstream; + } + + @Override + public final void create(ProxySurface s) { + if(null != upstream) { + upstream.create(s); + } + } + + @Override + public final void destroy(ProxySurface s) { + if(null != upstream) { + upstream.destroy(s); + } + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ "+ width + "x" + height + ", " + upstream + "]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java new file mode 100644 index 000000000..85e24582c --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java @@ -0,0 +1,54 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class DelegatedUpstreamSurfaceHookWithSurfaceSize implements UpstreamSurfaceHook { + final UpstreamSurfaceHook upstream; + final NativeSurface surface; + + /** + * @param upstream optional upstream UpstreamSurfaceHook used for {@link #create(ProxySurface)} and {@link #destroy(ProxySurface)}. + * @param surface mandatory {@link NativeSurface} used for {@link #getWidth(ProxySurface)} and {@link #getHeight(ProxySurface)} + */ + public DelegatedUpstreamSurfaceHookWithSurfaceSize(UpstreamSurfaceHook upstream, NativeSurface surface) { + this.upstream = upstream; + this.surface = surface; + if(null == surface) { + throw new IllegalArgumentException("given surface is null"); + } + } + + @Override + public final void create(ProxySurface s) { + if(null != upstream) { + upstream.create(s); + } + } + + @Override + public final void destroy(ProxySurface s) { + if(null != upstream) { + upstream.destroy(s); + } + } + + @Override + public final int getWidth(ProxySurface s) { + return surface.getWidth(); + } + + @Override + public final int getHeight(ProxySurface s) { + return surface.getHeight(); + } + + @Override + public String toString() { + final String us_s = null != surface ? ( surface.getClass().getName() + ": 0x" + Long.toHexString(surface.getSurfaceHandle()) + " " +surface.getWidth() + "x" + surface.getHeight() ) : "nil"; + return getClass().getSimpleName()+"["+upstream+", "+us_s+"]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java new file mode 100644 index 000000000..29c540ac4 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java @@ -0,0 +1,45 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class UpstreamSurfaceHookMutableSize implements UpstreamSurfaceHook.MutableSize { + int width, height; + + /** + * @param width initial width + * @param height initial height + */ + public UpstreamSurfaceHookMutableSize(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public final void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public final int getWidth(ProxySurface s) { + return width; + } + + @Override + public final int getHeight(ProxySurface s) { + return height; + } + @Override + public void create(ProxySurface s) { /* nop */ } + + @Override + public void destroy(ProxySurface s) { /* nop */ } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ "+ width + "x" + height + "]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java deleted file mode 100644 index b7f6ba45d..000000000 --- a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.nativewindow; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.ProxySurface; - -public class WrappedSurface extends ProxySurface { - protected long surfaceHandle; - - public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - super(cfg, initialWidth, initialHeight, upstream); - surfaceHandle=handle; - } - - @Override - protected void invalidateImpl() { - surfaceHandle = 0; - } - - @Override - public final long getSurfaceHandle() { - return surfaceHandle; - } - - @Override - public final void setSurfaceHandle(long surfaceHandle) { - this.surfaceHandle=surfaceHandle; - } - - @Override - protected final int lockSurfaceImpl() { - return LOCK_SUCCESS; - } - - @Override - protected final void unlockSurfaceImpl() { - } - - @Override - public String toString() { - final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); - final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; - - return "WrappedSurface[config " + getPrivateGraphicsConfiguration()+ - ", displayHandle 0x" + Long.toHexString(getDisplayHandle()) + - ", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle()) + - ", size " + getWidth() + "x" + getHeight() + - ", surfaceLock "+surfaceLock+ - ", upstreamSurfaceHook "+ush_s+"]"; - } -} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index d4b927cf1..a62d08ccf 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -39,12 +39,14 @@ package com.jogamp.nativewindow.awt; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; import java.awt.Component; import java.awt.Container; import java.applet.Applet; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; @@ -110,21 +112,6 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, this.offscreenSurfaceLayer = 0; } - @Override - public void setShallUseOffscreenLayer(boolean v) { - shallUseOffscreenLayer = v; - } - - @Override - public final boolean getShallUseOffscreenLayer() { - return shallUseOffscreenLayer; - } - - @Override - public final boolean isOffscreenLayerSurfaceEnabled() { - return isOffscreenLayerSurface; - } - protected synchronized void invalidate() { invalidateNative(); jawt = null; @@ -136,26 +123,29 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void invalidateNative(); - protected final void updateBounds(JAWT_Rectangle jawtBounds) { - if(DEBUG) { - final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight()); - if(!bounds.equals(jb)) { + protected final boolean updateBounds(JAWT_Rectangle jawtBounds) { + final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight()); + final boolean changed = !bounds.equals(jb); + + if(changed) { + if(DEBUG) { System.err.println("JAWTWindow.updateBounds: "+bounds+" -> "+jb); Thread.dumpStack(); } + bounds.setX(jawtBounds.getX()); + bounds.setY(jawtBounds.getY()); + bounds.setWidth(jawtBounds.getWidth()); + bounds.setHeight(jawtBounds.getHeight()); + + if(component instanceof Container) { + java.awt.Insets contInsets = ((Container)component).getInsets(); + insets.setLeftWidth(contInsets.left); + insets.setRightWidth(contInsets.right); + insets.setTopHeight(contInsets.top); + insets.setBottomHeight(contInsets.bottom); + } } - bounds.setX(jawtBounds.getX()); - bounds.setY(jawtBounds.getY()); - bounds.setWidth(jawtBounds.getWidth()); - bounds.setHeight(jawtBounds.getHeight()); - - if(component instanceof Container) { - java.awt.Insets contInsets = ((Container)component).getInsets(); - insets.setLeftWidth(contInsets.left); - insets.setRightWidth(contInsets.right); - insets.setTopHeight(contInsets.top); - insets.setBottomHeight(contInsets.bottom); - } + return changed; } /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */ @@ -181,9 +171,29 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, return jawt; } - /** - * {@inheritDoc} - */ + // + // OffscreenLayerOption + // + + @Override + public void setShallUseOffscreenLayer(boolean v) { + shallUseOffscreenLayer = v; + } + + @Override + public final boolean getShallUseOffscreenLayer() { + return shallUseOffscreenLayer; + } + + @Override + public final boolean isOffscreenLayerSurfaceEnabled() { + return isOffscreenLayerSurface; + } + + // + // OffscreenLayerSurface + // + @Override public final void attachSurfaceLayer(final long layerHandle) throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { @@ -205,9 +215,6 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void attachSurfaceLayerImpl(final long layerHandle); - /** - * {@inheritDoc} - */ @Override public final void detachSurfaceLayer() throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { @@ -232,11 +239,21 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void detachSurfaceLayerImpl(final long layerHandle); + protected final long getAttachedSurfaceLayer() { + return offscreenSurfaceLayer; + } + @Override public final boolean isSurfaceLayerAttached() { return 0 != offscreenSurfaceLayer; } + @Override + public final void setChosenCapabilities(CapabilitiesImmutable caps) { + ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps); + getPrivateGraphicsConfiguration().setChosenCapabilities(caps); + } + // // SurfaceUpdateListener // @@ -381,7 +398,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, public final AbstractGraphicsConfiguration getGraphicsConfiguration() { return config.getNativeGraphicsConfiguration(); } - + @Override public final long getDisplayHandle() { return getGraphicsConfiguration().getScreen().getDevice().getHandle(); @@ -393,13 +410,13 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } @Override - public int getWidth() { + public final int getWidth() { return component.getWidth(); } @Override - public int getHeight() { - return component.getHeight(); + public final int getHeight() { + return component.getHeight(); } // diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index 40042ec81..b824350ff 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -67,8 +67,8 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * Note that this is not an open connection, ie no native display handle exist. * This constructor exist to setup a default device connection/unit.
*/ - public EGLGraphicsDevice(String connection, int unitID) { - super(NativeWindowFactory.TYPE_EGL, connection, unitID); + public EGLGraphicsDevice() { + super(NativeWindowFactory.TYPE_EGL, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); this.nativeDisplayID[0] = 0 ; // EGL.EGL_DEFAULT_DISPLAY this.eglLifecycleCallback = null; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index cec7d4ec3..27462ae70 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -124,8 +124,11 @@ public interface NativeSurface extends SurfaceUpdatedListener { /** * Provide a mechanism to utilize custom (pre-) swap surface * code. This method is called before the render toolkit (e.g. JOGL) - * swaps the buffer/surface. The implementation may itself apply the swapping, + * swaps the buffer/surface if double buffering is enabled. + *

+ * The implementation may itself apply the swapping, * in which case true shall be returned. + *

* * @return true if this method completed swapping the surface, * otherwise false, in which case eg the GLDrawable diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index f7dbc6c27..f9800109c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -50,4 +50,7 @@ public interface OffscreenLayerSurface { /** Returns true if a surface layer is attached, otherwise false. */ public boolean isSurfaceLayerAttached(); + /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */ + public void setChosenCapabilities(CapabilitiesImmutable caps); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 7fc9789c2..395fdc818 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2012 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,242 +29,82 @@ package javax.media.nativewindow; import jogamp.nativewindow.Debug; -import jogamp.nativewindow.SurfaceUpdatedHelper; -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -public abstract class ProxySurface implements NativeSurface, MutableSurface { +/** + * Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an + * {@link UpstreamSurfaceHook} to influence the lifecycle and information. + * + * @see UpstreamSurfaceHook + * @see MutableSurface + * @see NativeSurface + */ +public interface ProxySurface extends MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); /** - * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int OWN_DEVICE = 1 << 7; + public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6; + + /** + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}. + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() + */ + public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7; /** * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int INVISIBLE_WINDOW = 1 << 8; + public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8; - /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ - public interface UpstreamSurfaceHook { - /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ - public void create(ProxySurface s); - /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ - public void destroy(ProxySurface s); + /** Allow redefining the AbstractGraphicsConfiguration */ + public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); - /** Returns the width of the upstream surface */ - public int getWidth(ProxySurface s); - /** Returns the height of the upstream surface */ - public int getHeight(ProxySurface s); - } + /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */ + public UpstreamSurfaceHook getUpstreamSurfaceHook(); - private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private final AbstractGraphicsConfiguration config; // control access due to delegation - private final UpstreamSurfaceHook upstream; - public final int initialWidth; - public final int initialHeight; - private long surfaceHandle_old; - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); - protected long displayHandle; - protected int scrnIndex; - protected int implBitfield; - /** - * @param cfg the {@link AbstractGraphicsConfiguration} to be used - * @param initialWidth the initial width - * @param initialHeight the initial height + * Sets the {@link UpstreamSurfaceHook} and returns the previous value. */ - protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - if(null == cfg) { - throw new IllegalArgumentException("null config"); - } - this.config = cfg; - this.upstream = upstream; - this.initialWidth = initialWidth; - this.initialHeight = initialHeight; - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - this.implBitfield = 0; - } - - public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook); + + /** + * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions + * {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}. + *

+ * Use this for small code blocks where the native resources shall not change, + * i.e. resizing a derived (OpenGL) drawable. + *

+ */ + public void enableUpstreamSurfaceHookLifecycle(boolean enable); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. */ - public void createNotify() { - if(null != upstream) { - upstream.create(this); - } - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - } + public void createNotify(); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, - * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared. */ - public void destroyNotify() { - if(null != upstream) { - upstream.destroy(this); - invalidateImpl(); - } - this.displayHandle = 0; - this.surfaceHandle_old = 0; - } + public void destroyNotify(); - /** - * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. - * @see #destroyNotify() - */ - protected void invalidateImpl() { - throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); - } + public StringBuilder getUpstreamOptionBits(StringBuilder sink); + public int getUpstreamOptionBits(); - @Override - public final long getDisplayHandle() { - return displayHandle; - } - - protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { - return config; - } - - @Override - public final AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config.getNativeGraphicsConfiguration(); - } - - @Override - public final int getScreenIndex() { - return getGraphicsConfiguration().getScreen().getIndex(); - } - - @Override - public abstract long getSurfaceHandle(); - - @Override - public abstract void setSurfaceHandle(long surfaceHandle); + /** Returns true if the give bit-mask v is set in this instance upstream-option-bits, otherwise false.*/ + public boolean containsUpstreamOptionBits(int v); - @Override - public final int getWidth() { - if(null != upstream) { - return upstream.getWidth(this); - } - return initialWidth; - } - - @Override - public final int getHeight() { - if(null != upstream) { - return upstream.getHeight(this); - } - return initialHeight; - } - - @Override - public boolean surfaceSwap() { - return false; - } - - @Override - public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.addSurfaceUpdatedListener(l); - } - - @Override - public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { - surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); - } - - @Override - public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); - } - - @Override - public void surfaceUpdated(Object updater, NativeSurface ns, long when) { - surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); - } - - @Override - public int lockSurface() throws NativeWindowException, RuntimeException { - surfaceLock.lock(); - int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? - - if ( LOCK_SURFACE_NOT_READY == res ) { - try { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - adevice.lock(); - try { - res = lockSurfaceImpl(); - if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) { - res = LOCK_SURFACE_CHANGED; - if(DEBUG) { - System.err.println("ProxySurface: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle())); - // Thread.dumpStack(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - adevice.unlock(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - surfaceLock.unlock(); - } - } - } - return res; - } - - @Override - public final void unlockSurface() { - surfaceLock.validateLocked(); - surfaceHandle_old = getSurfaceHandle(); - - if (surfaceLock.getHoldCount() == 1) { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - try { - unlockSurfaceImpl(); - } finally { - adevice.unlock(); - } - } - surfaceLock.unlock(); - } - - protected abstract int lockSurfaceImpl(); - - protected abstract void unlockSurfaceImpl() ; - - public final void validateSurfaceLocked() { - surfaceLock.validateLocked(); - } - - @Override - public final boolean isSurfaceLockedByOtherThread() { - return surfaceLock.isLockedByOtherThread(); - } - - @Override - public final Thread getSurfaceLockOwner() { - return surfaceLock.getOwner(); - } + /** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ v.*/ + public void addUpstreamOptionBits(int v); - @Override - public abstract String toString(); + /** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ ~v*/ + public void clearUpstreamOptionBits(int v); - public int getImplBitfield() { return implBitfield; } - public void setImplBitfield(int v) { implBitfield=v; } + public StringBuilder toString(StringBuilder sink); + public String toString(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java new file mode 100644 index 000000000..6fe2e5364 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java @@ -0,0 +1,52 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +/** + * Interface allowing upstream caller to pass lifecycle actions and size info + * to a {@link ProxySurface} instance. + */ +public interface UpstreamSurfaceHook { + /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ + public void create(ProxySurface s); + /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ + public void destroy(ProxySurface s); + + /** Returns the width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getHeight(ProxySurface s); + + /** + * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize. + */ + public interface MutableSize extends UpstreamSurfaceHook { + public void setSize(int width, int height); + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java new file mode 100644 index 000000000..63f56cbae --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java @@ -0,0 +1,326 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.nativewindow.UpstreamSurfaceHook; + + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +public abstract class ProxySurfaceImpl implements ProxySurface { + private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + protected long displayHandle; // convenient ref of config.screen.device.handle + private AbstractGraphicsConfiguration config; // control access due to delegation + private UpstreamSurfaceHook upstream; + private long surfaceHandle_old; + private RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + private int implBitfield; + private boolean upstreamSurfaceHookLifecycleEnabled; + + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) { + if(null == cfg) { + throw new IllegalArgumentException("null AbstractGraphicsConfiguration"); + } + if(null == upstream) { + throw new IllegalArgumentException("null UpstreamSurfaceHook"); + } + this.config = cfg; + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.upstream = upstream; + this.surfaceHandle_old = 0; + this.implBitfield = 0; + this.upstreamSurfaceHookLifecycleEnabled = true; + if(ownsDevice) { + addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } + + @Override + public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + + @Override + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) { + if(null == hook) { + throw new IllegalArgumentException("null UpstreamSurfaceHook"); + } + upstream = hook; + } + + @Override + public final void enableUpstreamSurfaceHookLifecycle(boolean enable) { + upstreamSurfaceHookLifecycleEnabled = enable; + } + + @Override + public void createNotify() { + if(upstreamSurfaceHookLifecycleEnabled) { + upstream.create(this); + } + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; + } + + @Override + public void destroyNotify() { + if(upstreamSurfaceHookLifecycleEnabled) { + upstream.destroy(this); + if( containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) { + final AbstractGraphicsDevice aDevice = getGraphicsConfiguration().getScreen().getDevice(); + aDevice.close(); + clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + invalidateImpl(); + } + this.displayHandle = 0; + this.surfaceHandle_old = 0; + } + + /** + * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. + * @see #destroyNotify() + */ + protected void invalidateImpl() { + throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); + } + + @Override + public final long getDisplayHandle() { + return displayHandle; + } + + protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { + return config; + } + + @Override + public final AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config.getNativeGraphicsConfiguration(); + } + + @Override + public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) { + config = cfg; + } + + @Override + public final int getScreenIndex() { + return getGraphicsConfiguration().getScreen().getIndex(); + } + + @Override + public abstract long getSurfaceHandle(); + + @Override + public abstract void setSurfaceHandle(long surfaceHandle); + + @Override + public final int getWidth() { + return upstream.getWidth(this); + } + + @Override + public final int getHeight() { + return upstream.getHeight(this); + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.addSurfaceUpdatedListener(l); + } + + @Override + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); + } + + @Override + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); + } + + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + surfaceLock.lock(); + int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? + + if ( LOCK_SURFACE_NOT_READY == res ) { + try { + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); + adevice.lock(); + try { + res = lockSurfaceImpl(); + if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) { + res = LOCK_SURFACE_CHANGED; + if(DEBUG) { + System.err.println("ProxySurfaceImpl: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle())); + // Thread.dumpStack(); + } + } + } finally { + if (LOCK_SURFACE_NOT_READY >= res) { + adevice.unlock(); + } + } + } finally { + if (LOCK_SURFACE_NOT_READY >= res) { + surfaceLock.unlock(); + } + } + } + return res; + } + + @Override + public final void unlockSurface() { + surfaceLock.validateLocked(); + surfaceHandle_old = getSurfaceHandle(); + + if (surfaceLock.getHoldCount() == 1) { + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); + try { + unlockSurfaceImpl(); + } finally { + adevice.unlock(); + } + } + surfaceLock.unlock(); + } + + protected abstract int lockSurfaceImpl(); + + protected abstract void unlockSurfaceImpl() ; + + public final void validateSurfaceLocked() { + surfaceLock.validateLocked(); + } + + @Override + public final boolean isSurfaceLockedByOtherThread() { + return surfaceLock.isLockedByOtherThread(); + } + + @Override + public final Thread getSurfaceLockOwner() { + return surfaceLock.getOwner(); + } + + public final StringBuilder getUpstreamOptionBits(StringBuilder sink) { + if(null == sink) { + sink = new StringBuilder(); + } + sink.append("UOB[ "); + if(0 == implBitfield) { + sink.append("]"); + return sink; + } + boolean needsOr = false; + if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + sink.append("OWNS_SURFACE"); + needsOr = true; + } + if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) { + if(needsOr) { + sink.append(" | "); + } + sink.append("OWNS_DEVICE"); + needsOr = true; + } + if( 0 != ( implBitfield & OPT_UPSTREAM_WINDOW_INVISIBLE ) ) { + if(needsOr) { + sink.append(" | "); + } + sink.append("WINDOW_INVISIBLE"); + needsOr = true; + } + sink.append(" ]"); + return sink; + } + + @Override + public final int getUpstreamOptionBits() { return implBitfield; } + + @Override + public final boolean containsUpstreamOptionBits(int v) { + return v == ( implBitfield & v ) ; + } + + @Override + public final void addUpstreamOptionBits(int v) { implBitfield |= v; } + + @Override + public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; } + + @Override + public StringBuilder toString(StringBuilder sink) { + if(null == sink) { + sink = new StringBuilder(); + } + sink.append(getUpstreamSurfaceHook()). + append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())). + append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())). + append(", size " + getWidth() + "x" + getHeight()).append(", "); + getUpstreamOptionBits(sink); + sink.append(", surfaceLock "+surfaceLock); + return sink; + } + + @Override + public String toString() { + StringBuilder msg = new StringBuilder(); + msg.append(getClass().getSimpleName()).append("[ "); + toString(msg); + msg.append(" ]"); + return msg.toString(); + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java new file mode 100644 index 000000000..e544bc61a --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java @@ -0,0 +1,95 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class WrappedSurface extends ProxySurfaceImpl { + protected long surfaceHandle; + + /** + * Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information, + * which is being passed to the {@link ProxySurface} instance. + * + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined + * @param initialWidth + * @param initialHeight + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) { + super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice); + surfaceHandle=handle; + } + + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. + */ + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) { + super(cfg, upstream, ownsDevice); + surfaceHandle=handle; + } + + @Override + protected void invalidateImpl() { + surfaceHandle = 0; + } + + @Override + public final long getSurfaceHandle() { + return surfaceHandle; + } + + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.surfaceHandle=surfaceHandle; + } + + @Override + protected final int lockSurfaceImpl() { + return LOCK_SUCCESS; + } + + @Override + protected final void unlockSurfaceImpl() { + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index e81d61e0f..5fd242247 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -51,7 +51,6 @@ import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Point; -import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.awt.JAWTWindow; import jogamp.nativewindow.jawt.JAWT; @@ -71,17 +70,18 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { } protected void invalidateNative() { - surfaceHandle=0; + offscreenSurfaceHandle=0; + offscreenSurfaceHandleSet=false; if(isOffscreenLayerSurfaceEnabled()) { if(0 != rootSurfaceLayerHandle) { OSXUtil.DestroyCALayer(rootSurfaceLayerHandle); rootSurfaceLayerHandle = 0; } - if(0 != drawable) { - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; + if(0 != windowHandle) { + OSXUtil.DestroyNSWindow(windowHandle); } } + windowHandle=0; } protected void attachSurfaceLayerImpl(final long layerHandle) { @@ -92,8 +92,14 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle); } - public long getSurfaceHandle() { - return isOffscreenLayerSurfaceEnabled() ? surfaceHandle : super.getSurfaceHandle() ; + @Override + public final long getWindowHandle() { + return windowHandle; + } + + @Override + public final long getSurfaceHandle() { + return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ; } public void setSurfaceHandle(long surfaceHandle) { @@ -103,7 +109,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { if(DEBUG) { System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); } - this.surfaceHandle = surfaceHandle; + this.offscreenSurfaceHandle = surfaceHandle; + this.offscreenSurfaceHandleSet = true; } protected JAWT fetchJAWTImpl() throws NativeWindowException { @@ -167,6 +174,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { unlockSurfaceImpl(); return NativeWindow.LOCK_SURFACE_NOT_READY; } else { + windowHandle = OSXUtil.GetNSWindow(drawable); ret = NativeWindow.LOCK_SUCCESS; } } else { @@ -177,36 +185,46 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { * The actual surface/ca-layer shall be created/attached * by the upper framework (JOGL) since they require more information. */ + String errMsg = null; if(0 == drawable) { - drawable = OSXUtil.CreateNSWindow(0, 0, getBounds().getWidth(), getBounds().getHeight()); - if(0 == drawable) { - unlockSurfaceImpl(); - throw new NativeWindowException("Unable to created dummy NSWindow (layered case)"); + windowHandle = OSXUtil.CreateNSWindow(0, 0, 64, 64); + if(0 == windowHandle) { + errMsg = "Unable to create dummy NSWindow (layered case)"; + } else { + drawable = OSXUtil.GetNSView(windowHandle); + if(0 == drawable) { + errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle); + } + } + if(null == errMsg) { + // fix caps reflecting offscreen! (no GL available here ..) + Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable(); + caps.setOnscreen(false); + setChosenCapabilities(caps); } - // fix caps reflecting offscreen! - Capabilities caps = (Capabilities) getPrivateGraphicsConfiguration().getChosenCapabilities().cloneMutable(); - caps.setOnscreen(false); - getPrivateGraphicsConfiguration().setChosenCapabilities(caps); - caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable(); - caps.setOnscreen(false); - ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps); } - if(0 == rootSurfaceLayerHandle) { - rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); - if(0 == rootSurfaceLayerHandle) { - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; - unlockSurfaceImpl(); - throw new NativeWindowException("Could not create root CALayer: "+this); + if(null == errMsg) { + if(0 == rootSurfaceLayerHandle) { + rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); + if(0 == rootSurfaceLayerHandle) { + errMsg = "Could not create root CALayer"; + } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) { + errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle); + } } - if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) { + } + if(null != errMsg) { + if(0 != rootSurfaceLayerHandle) { OSXUtil.DestroyCALayer(rootSurfaceLayerHandle); rootSurfaceLayerHandle = 0; - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; - unlockSurfaceImpl(); - throw new NativeWindowException("Could not set JAWT rootSurfaceLayerHandle: "+this); } + if(0 != windowHandle) { + OSXUtil.DestroyNSWindow(windowHandle); + windowHandle = 0; + } + drawable = 0; + unlockSurfaceImpl(); + throw new NativeWindowException(errMsg+": "+this); } ret = NativeWindow.LOCK_SUCCESS; } @@ -264,7 +282,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer - private long surfaceHandle = 0; + private long windowHandle = 0; + private long offscreenSurfaceHandle = 0; + private boolean offscreenSurfaceHandleSet = false; // Workaround for instance of 4796548 private boolean firstLock = true; diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..de3206c0c --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java @@ -0,0 +1,56 @@ +package jogamp.nativewindow.macosx; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + long nsWindow; + + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public OSXDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + nsWindow = 0; + } + + @Override + public final void create(ProxySurface s) { + if(0 == nsWindow && 0 == s.getSurfaceHandle()) { + nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64); + if(0 == nsWindow) { + throw new NativeWindowException("Error NS window 0"); + } + long nsView = OSXUtil.GetNSView(nsWindow); + if(0 == nsView) { + throw new NativeWindowException("Error NS view 0"); + } + s.setSurfaceHandle(nsView); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow)); + } + OSXUtil.DestroyNSWindow(nsWindow); + nsWindow = 0; + s.setSurfaceHandle(0); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 149ebdf4a..b7a83e133 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -72,6 +72,10 @@ public class OSXUtil { return isNSView0(object); } + public static boolean isNSWindow(long object) { + return isNSWindow0(object); + } + /** * In case the windowOrView is top-level, * you shall set topLevel to true where @@ -114,6 +118,9 @@ public class OSXUtil { public static long GetNSView(long nsWindow) { return GetNSView0(nsWindow); } + public static long GetNSWindow(long nsView) { + return GetNSWindow0(nsView); + } public static long CreateCALayer(int x, int y, int width, int height) { return CreateCALayer0(x, y, width, height); @@ -149,6 +156,11 @@ public class OSXUtil { return IsMainThread0(); } + /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */ + public static int GetScreenRefreshRate(int scrn_idx) { + return GetScreenRefreshRate0(scrn_idx); + } + /*** private static boolean isAWTEDTMainThreadInit = false; private static boolean isAWTEDTMainThread; @@ -172,15 +184,18 @@ public class OSXUtil { private static native boolean initIDs0(); private static native boolean isNSView0(long object); + private static native boolean isNSWindow0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); + private static native long GetNSWindow0(long nsView); private static native long CreateCALayer0(int x, int y, int width, int height); private static native void AddCASublayer0(long rootCALayer, long subCALayer); private static native void RemoveCASublayer0(long rootCALayer, long subCALayer); private static native void DestroyCALayer0(long caLayer); private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable); private static native boolean IsMainThread0(); + private static native int GetScreenRefreshRate0(int scrn_idx); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..aa5f3dac5 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java @@ -0,0 +1,50 @@ +package jogamp.nativewindow.windows; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public GDIDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if(0 == ms.getWindowHandle()) { + final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64); + if(0 == windowHandle) { + throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError()); + } + ms.setWindowHandle(windowHandle); + ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( 0 == ms.getWindowHandle() ) { + throw new InternalError("Owns upstream surface, but no GDI window: "+ms); + } + GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE); + GDIUtil.DestroyDummyWindow(ms.getWindowHandle()); + ms.setWindowHandle(0); + ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java index e368aa6a1..3db2b5fc9 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java @@ -29,9 +29,13 @@ package jogamp.nativewindow.windows; import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import jogamp.nativewindow.ProxySurfaceImpl; +import jogamp.nativewindow.windows.GDI; /** @@ -40,12 +44,20 @@ import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; * The latter will get and release the HDC. * The size via getWidth()/getHeight() is invalid. */ -public class GDISurface extends ProxySurface { +public class GDISurface extends ProxySurfaceImpl { protected long windowHandle; protected long surfaceHandle; - public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - super(cfg, initialWidth, initialHeight, upstream); + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param windowHandle the wrapped pre-existing native window handle, maybe 0 if not yet determined + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) { + super(cfg, upstream, ownsDevice); this.windowHandle=windowHandle; this.surfaceHandle=0; } @@ -114,18 +126,4 @@ public class GDISurface extends ProxySurface { final public long getSurfaceHandle() { return surfaceHandle; } - - @Override - final public String toString() { - final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); - final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; - return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ - ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ - ", windowHandle 0x"+Long.toHexString(windowHandle)+ - ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ - ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+ - ", upstreamSurfaceHook "+ush_s+"]"; - } - } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..55a29dd5e --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java @@ -0,0 +1,60 @@ +package jogamp.nativewindow.x11; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import jogamp.nativewindow.x11.X11Lib; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; +import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; + +public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public X11DummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration(); + final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen(); + final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + if(0 == device.getHandle()) { + device.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( 0 == s.getSurfaceHandle() ) { + final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64); + if(0 == windowHandle) { + throw new NativeWindowException("Creating dummy window failed w/ "+cfg); + } + s.setSurfaceHandle(windowHandle); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( 0 == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no X11 window: "+s); + } + X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(0); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 2c853a43d..d6ae7ed31 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -119,6 +119,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, j return [nsObj isMemberOfClass:[NSView class]]; } +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + return [nsObj isMemberOfClass:[NSWindow class]]; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: getLocationOnScreen0 @@ -238,8 +244,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 [myWindow setPreservesContentDuringLiveResize: YES]; // Remove animations NS_DURING + if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { // Available >= 10.7 - Removes default animations [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + } NS_HANDLER NS_ENDHANDLER @@ -278,11 +286,28 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); - DBG_PRINT( "contentView0 - window: %p (START)\n", win); - jlong res = (jlong) ((intptr_t) [win contentView]); - DBG_PRINT( "contentView0 - window: %p (END)\n", win); + DBG_PRINT( "GetNSView(window: %p): %p\n", win, (void*) (intptr_t) res); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSWindow0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSView* v = (NSView*) ((intptr_t) view); + + jlong res = (jlong) ((intptr_t) [v window]); + + DBG_PRINT( "GetNSWindow(view: %p): %p\n", v, (void*) (intptr_t) res); [pool release]; return res; @@ -314,6 +339,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0 // no animations for add/remove/swap sublayers etc // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] [layer removeAllAnimations]; + [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [layer setNeedsDisplayOnBoundsChange: YES]; DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height); DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); @@ -357,7 +384,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0 // no animations for add/remove/swap sublayers etc // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] [rootLayer removeAllAnimations]; + [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [rootLayer setNeedsDisplayOnBoundsChange: YES]; [subLayer removeAllAnimations]; + [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [subLayer setNeedsDisplayOnBoundsChange: YES]; }]; DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]); JNF_COCOA_EXIT(env); @@ -404,6 +435,63 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0 JNF_COCOA_EXIT(env); } +/* + * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow + * Method: SetJAWTRootSurfaceLayer0 + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0 + (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); + if (NULL == dsi) { + NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); + return JNI_FALSE; + } + CALayer* layer = (CALayer*) (intptr_t) caLayer; + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + id surfaceLayers = (id )dsi->platformInfo; + DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]); + surfaceLayers.layer = layer; // already incr. retain count + DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); + }]; + JNF_COCOA_EXIT(env); + return JNI_TRUE; +} + +/* + * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow + * Method: UnsetJAWTRootSurfaceLayer0 + * Signature: (JJ)Z +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0 + (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); + if (NULL == dsi) { + NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); + return JNI_FALSE; + } + CALayer* layer = (CALayer*) (intptr_t) caLayer; + { + id surfaceLayers = (id )dsi->platformInfo; + if(layer != surfaceLayers.layer) { + NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); + return JNI_FALSE; + } + } + // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + id surfaceLayers = (id )dsi->platformInfo; + DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer); + surfaceLayers.layer = NULL; + [layer release]; + // }]; + JNF_COCOA_EXIT(env); + return JNI_TRUE; +} + */ + @interface MainRunnable : NSObject { @@ -489,60 +577,65 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0 return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ; } -/* - * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow - * Method: SetJAWTRootSurfaceLayer0 - * Signature: (JJ)Z +/*** + * The following static functions are copied out of NEWT's OSX impl. + * May need to push code to NativeWindow, to remove duplication. */ -JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0 - (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + return (NSScreen *) [screens objectAtIndex: screen_idx]; +} +static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { + // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + NSDictionary * dict = [screen deviceDescription]; + NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; + // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size + return (CGDirectDisplayID) [val integerValue]; +} +static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) { - JNF_COCOA_ENTER(env); - JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); - if (NULL == dsi) { - NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); - return JNI_FALSE; - } - CALayer* layer = (CALayer*) (intptr_t) caLayer; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - id surfaceLayers = (id )dsi->platformInfo; - DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]); - surfaceLayers.layer = layer; // already incr. retain count - DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); - }]; - JNF_COCOA_EXIT(env); - return JNI_TRUE; + long value = 0; + CFNumberRef numRef; + numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); + if (numRef != NULL) + CFNumberGetValue(numRef, kCFNumberLongType, &value); + return value; } +#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) /* - * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow - * Method: UnsetJAWTRootSurfaceLayer0 - * Signature: (JJ)Z -JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0 - (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetScreenRefreshRate + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshRate0 + (JNIEnv *env, jclass unused, jint scrn_idx) { + int res = 0; JNF_COCOA_ENTER(env); - JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); - if (NULL == dsi) { - NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); - return JNI_FALSE; - } - CALayer* layer = (CALayer*) (intptr_t) caLayer; - { - id surfaceLayers = (id )dsi->platformInfo; - if(layer != surfaceLayers.layer) { - NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); - return JNI_FALSE; + // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + DBG_PRINT("GetScreenRefreshRate.0: screen %p\n", (void *)screen); + if(NULL != screen) { + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)display); + if(0 != display) { + CFDictionaryRef mode = CGDisplayCurrentMode(display); + DBG_PRINT("GetScreenRefreshRate.2: mode %p\n", (void *)mode); + if(NULL != mode) { + res = CGDDGetModeRefreshRate(mode); + DBG_PRINT("GetScreenRefreshRate.3: res %d\n", res); + } } } - // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - id surfaceLayers = (id )dsi->platformInfo; - DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer); - surfaceLayers.layer = NULL; - [layer release]; - // }]; + if(0 == res) { + res = 60; // default .. (experienced on OSX 10.6.8) + } + fprintf(stderr, "GetScreenRefreshRate.X: %d\n", res); + // [pool release]; JNF_COCOA_EXIT(env); - return JNI_TRUE; + return res; } - */ diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 6f0028a77..89a749c51 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -68,6 +68,15 @@ import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; +/** + * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting. + * + *
Offscreen Layer Remarks
+ * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + */ @SuppressWarnings("serial") public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption { public static final boolean DEBUG = Debug.debug("Window"); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 0fc1b4e89..a89ccaedb 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -51,6 +51,7 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; @@ -97,7 +98,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind * Constructor. Do not call this directly -- use {@link #create()} instead. */ protected GLWindow(Window window) { - super(null, null, false); + super(null, null, false /* always handle device lifecycle ourselves */); this.window = (WindowImpl) window; this.window.setHandleDestroyNotify(false); window.addWindowListener(new WindowAdapter() { @@ -107,8 +108,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override - public void windowResized(WindowEvent e) { - defaultWindowResizedOp(); + public void windowResized(WindowEvent e) { + defaultWindowResizedOp(getWidth(), getHeight()); } @Override @@ -201,11 +202,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind @Override public final CapabilitiesImmutable getChosenCapabilities() { - if (drawable == null) { - return window.getChosenCapabilities(); - } - - return drawable.getChosenGLCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities(); } @Override @@ -536,19 +534,24 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return; } + final boolean done; final RecursiveLock lock = window.getLock(); lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating try { if( null != context ) { // surface is locked/unlocked implicit by context's makeCurrent/release helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); - } else if( 0 display - setVisible(true); + done = true; + } else { + done = false; } } finally { lock.unlock(); } + if( !done && 0 display + setVisible(true); + } } //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index cada253bc..36bc3f28f 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -63,6 +63,9 @@ import com.jogamp.newt.Window; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.util.EDTUtil; +/** + * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting. + */ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("Window"); private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index ba98ca3af..c6c1814f6 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -39,20 +39,16 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; public class OffscreenWindow extends WindowImpl implements MutableSurface { - long surfaceHandle = 0; - ProxySurface.UpstreamSurfaceHook upstreamHook; - ProxySurface dummySurface; + long surfaceHandle; public OffscreenWindow() { - upstreamHook = null; - dummySurface = null; + surfaceHandle = 0; } static long nextWindowHandle = 0x100; // start here - a marker @@ -62,17 +58,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - /** Cannot use OpenGL here .. - if(capsRequested instanceof GLCapabilitiesImmutable) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; - if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { - final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); - final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); - upstreamHook = dummySurface.getUpstreamSurfaceHook(); - dummySurface.createNotify(); - } - } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { @@ -83,6 +68,7 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { synchronized(OffscreenWindow.class) { setWindowHandle(nextWindowHandle++); } + visibleChanged(false, true); } protected void closeNativeImpl() { @@ -92,11 +78,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public synchronized void destroy() { super.destroy(); - if(null != dummySurface) { - dummySurface.destroyNotify(); - dummySurface = null; - upstreamHook = null; - } surfaceHandle = 0; } @@ -106,10 +87,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public long getSurfaceHandle() { - if(null != dummySurface) { - return dummySurface.getSurfaceHandle(); - // return upstreamHook.getWidth(); - } return surfaceHandle; } @@ -128,8 +105,8 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + sizeChanged(false, width, height, false); if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - sizeChanged(false, width, height, false); visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); } else { /** diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index ad7195944..c1ac87d38 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -767,11 +767,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void setVisible(boolean visible) { + protected void setVisible(boolean wait, boolean visible) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); } - runOnEDTIfAvail(true, new VisibleAction(visible)); + runOnEDTIfAvail(wait, new VisibleAction(visible)); + } + + public void setVisible(boolean visible) { + setVisible(true, visible); } private class SetSizeAction implements Runnable { @@ -783,21 +787,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - boolean recreate = false; final RecursiveLock _lock = windowLock; _lock.lock(); try { if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) { - recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); - } - if(recreate) { - // will trigger visibleAction:=2 -> create if wasVisible - final boolean wasVisible = WindowImpl.this.visible; - screen.addReference(); // retain screen - destroyAction.run(); - WindowImpl.this.visible = wasVisible; + System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); } int visibleAction; // 0 nop, 1 invisible, 2 visible (create) if ( isNativeValid() && 0>=width*height && visible ) { @@ -823,9 +818,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - if(recreate) { - screen.removeReference(); // bring back ref-count - } _lock.unlock(); } } @@ -940,11 +932,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) { boolean ofs = false; - if( null != cWin.getGraphicsConfiguration() ) { - ofs = !cWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration(); + if( null != cWinCfg ) { + ofs = !cWinCfg.getChosenCapabilities().isOnscreen(); } - if( !ofs && null != pWin && null != pWin.getGraphicsConfiguration() ) { - ofs |= !pWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + if( !ofs && null != pWin ) { + final AbstractGraphicsConfiguration pWinCfg = pWin.getGraphicsConfiguration(); + if( null != pWinCfg ) { + ofs = !pWinCfg.getChosenCapabilities().isOnscreen(); + } } return ofs; } diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 276b0d070..f18520630 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -428,7 +428,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); if(isVisible()) { - setVisible(true); + setVisible(false, true); } } sizeChanged(false, aWidth, aHeight, false); diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index ea48569bf..d0c0b8b20 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -117,6 +117,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; } + @Override public void setSurfaceHandle(long surfaceHandle) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); @@ -170,13 +171,22 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - final Point pS = getTopLevelLocationOnScreen(x, y); - isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); + final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); + isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; + final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y); if(DEBUG_IMPLEMENTATION) { + final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); + final NativeWindow pWin = getParent(); + final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null; System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ - ", offscreenInstance "+isOffscreenInstance+ - ", "+getReconfigureFlagsAsString(null, flags)); + ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+ + ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+ + ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+ + ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+ + ", ioi: "+_isOffscreenInstance+ + ") -> "+isOffscreenInstance+ + "\n\t, "+getReconfigureFlagsAsString(null, flags)); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { @@ -190,7 +200,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl 0 != ( FLAG_CHANGE_DECORATION & flags) || 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + if(isOffscreenInstance) { + createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false); + } else { + createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } } if(x>=0 && y>=0) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index e0330a563..b9c339285 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -94,7 +94,13 @@ static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pvi if(NULL!=oldNSView) { NS_DURING // Available >= 10.5 - Makes the menubar disapear - if([oldNSView isInFullScreenMode]) { + BOOL iifs; + if ( [oldNSView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [oldNSView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [oldNSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [oldNSView exitFullScreenModeWithOptions: NULL]; } NS_HANDLER @@ -430,6 +436,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree if( -1 < mode_idx ) { prop[propIndex++] = mode_idx; } + int refreshRate = CGDDGetModeRefreshRate(mode); + int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8) prop[propIndex++] = 0; // set later for verification of iterator propIndexRes = propIndex; prop[propIndex++] = mWidth; @@ -437,14 +445,14 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); prop[propIndex++] = widthMM; prop[propIndex++] = heightMM; - prop[propIndex++] = CGDDGetModeRefreshRate(mode); + prop[propIndex++] = fRefreshRate; prop[propIndex++] = ccwRot; prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL - DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n", + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n", (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], - (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]); + (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]); jintArray properties = (*env)->NewIntArray(env, prop_num); if (properties == NULL) { @@ -516,6 +524,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 if(initialized) return JNI_TRUE; initialized = 1; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { @@ -537,7 +547,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 // printf("Going to sleep for 10 seconds\n"); // sleep(10); - return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; + BOOL res = [NewtMacWindow initNatives: env forClass: clazz]; + [pool release]; + + return (jboolean) res; } /* @@ -602,8 +615,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow // Remove animations for child windows if(NULL != parentWindow) { NS_DURING - // Available >= 10.7 - Removes default animations - [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + } NS_HANDLER NS_ENDHANDLER } @@ -658,8 +673,12 @@ NS_ENDHANDLER NS_DURING // concurrent view rendering // Available >= 10.6 - Makes the menubar disapear - [myWindow setAllowsConcurrentViewDrawing: YES]; - [myView setCanDrawConcurrently: YES]; + if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) { + [myWindow setAllowsConcurrentViewDrawing: YES]; + } + if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { + [myView setCanDrawConcurrently: YES]; + } NS_HANDLER NS_ENDHANDLER @@ -669,7 +688,9 @@ NS_ENDHANDLER NS_DURING // Available >= 10.5 - Makes the menubar disapear if(fullscreen) { - [myView enterFullScreenMode: myScreen withOptions:NULL]; + if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { + [myView enterFullScreenMode: myScreen withOptions:NULL]; + } } NS_HANDLER NS_ENDHANDLER @@ -730,7 +751,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 NS_DURING if(NULL!=mView) { // Available >= 10.5 - Makes the menubar disapear - if([mView isInFullScreenMode]) { + BOOL iifs; + if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [mView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [mView exitFullScreenModeWithOptions: NULL]; } // Note: mWin's release will also release it's mView! diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java index 4f24fc9b8..c4b74c56f 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java @@ -50,6 +50,8 @@ public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLaunche // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); // props.setProperty("nativewindow.debug", "all"); props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java index c75c229a8..576305835 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java @@ -14,23 +14,23 @@ public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLaun final OrderedProperties props = getProperties(); // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); - // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // properties.setProperty("jogamp.debug.IOUtil", "true"); - // properties.setProperty("nativewindow.debug", "all"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); - // properties.setProperty("jogl.debug", "all"); - // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); props.setProperty("jogl.debug.CapabilitiesChooser", "true"); - // properties.setProperty("jogl.debug.GLSLState", "true"); - // properties.setProperty("jogl.debug.DebugGL", "true"); - // properties.setProperty("jogl.debug.TraceGL", "true"); - // properties.setProperty("newt.debug", "all"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); props.setProperty("newt.debug.Window", "true"); - // properties.setProperty("newt.debug.Window.MouseEvent", "true"); - // properties.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java new file mode 100644 index 000000000..eab1a37e3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java @@ -0,0 +1,128 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.common.util.RunnableTask; +import com.jogamp.opengl.test.junit.util.UITestCase; + +public class TestFBOAutoDrawableDeadlockAWT extends UITestCase { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull( glp ); + width = 512; + height = 512; + } + + protected void runTestGL( GLCapabilities caps ) throws InterruptedException, InvocationTargetException { + final GLOffscreenAutoDrawable fbod = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable( + null, + caps, new DefaultGLCapabilitiesChooser(), + 512, 512, + null + ); + + final boolean[] done = {false}; + final Runnable pbufferCreationAction = new Runnable() { + public void run() { + System.err.println("AA.1"); + fbod.display(); + done[ 0 ] = true; + System.err.println("AA.X"); + } + }; + + EventQueue.invokeAndWait(new Runnable() { + public void run() { + Assert.assertTrue(EventQueue.isDispatchThread()); + JAWTUtil.lockToolkit(); + try { + final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false); + System.err.println("BB.0: "+rTask.getSyncObject()); + synchronized (rTask.getSyncObject()) { + System.err.println("BB.1: "+rTask.getSyncObject()); + new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); + try { + System.err.println("BB.2"); + rTask.getSyncObject().wait(); + System.err.println("BB.3"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + System.err.println("BB.X"); + } + } finally { + JAWTUtil.unlockToolkit(); + } + } + }); + Assert.assertTrue(done[0]); + fbod.destroy(); + } + + @Test(timeout = 2000) // 2s timeout + public void testDeadlock() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities( glp ); + runTestGL( caps ); + } + + static long duration = 500; // ms + + public static void main( String args[] ) { + for ( int i = 0; i < args.length; i++ ) { + if ( args[ i ].equals( "-time" ) ) { + i++; + try { + duration = Integer.parseInt( args[ i ] ); + } + catch ( Exception ex ) { + ex.printStackTrace(); + } + } + } + org.junit.runner.JUnitCore.main( TestFBOAutoDrawableDeadlockAWT.class.getName() ); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java new file mode 100644 index 000000000..2dc547f39 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java @@ -0,0 +1,375 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

+ *

+ * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. + *

+ */ +public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + @Test + public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(false); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); // default + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep, null); + Assert.assertNotNull(glad); + + System.out.println("Realized GLAD: "+glad); + System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); + Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); + + glad.display(); // initial display incl. init! + { + final GLContext context = glad.getContext(); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); + + // + // FBO incl. MSAA is fully initialized now + // + + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Init GLAD: "+glad); + System.out.println("Init GLAD: "+chosenCaps); + + final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject fboBack = glad.getFBObject(GL.GL_BACK); + + System.out.println("Init front FBO: "+fboFront); + System.out.println("Init back FBO: "+fboBack); + + Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); + Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); + Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); + + if( chosenCaps.getDoubleBuffered() ) { + Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack)); + Assert.assertNotSame(fboFront, fboBack); + } else { + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack)); + Assert.assertSame(fboFront, fboBack); + } + + final FBObject.TextureAttachment texAttachA, texAttachB; + + texAttachA = glad.getTextureBuffer(GL.GL_FRONT); + if(0==glad.getNumSamples()) { + texAttachB = glad.getTextureBuffer(GL.GL_BACK); + } else { + texAttachB = null; + } + + final FBObject.Colorbuffer colorA, colorB; + final FBObject.RenderAttachment depthA, depthB; + + colorA = fboFront.getColorbuffer(0); + Assert.assertNotNull(colorA); + colorB = fboBack.getColorbuffer(0); + Assert.assertNotNull(colorB); + + depthA = fboFront.getDepthAttachment(); + Assert.assertNotNull(depthA); + depthB = fboBack.getDepthAttachment(); + Assert.assertNotNull(depthB); + + glad.display(); // SWAP_ODD + + if( chosenCaps.getDoubleBuffered() ) { + // double buffer or MSAA + Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA)); + Assert.assertNotSame(colorB, colorA); + Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA)); + Assert.assertNotSame(depthB, depthA); + } else { + // single buffer + Assert.assertEquals(colorA, colorB); + Assert.assertSame(colorA, colorB); + Assert.assertEquals(depthA, depthB); + Assert.assertSame(depthA, depthB); + } + + Assert.assertEquals(texAttachA, colorA); + Assert.assertSame(texAttachA, colorA); + if(0==glad.getNumSamples()) { + Assert.assertEquals(texAttachB, colorB); + Assert.assertSame(texAttachB, colorB); + } + + if( chosenCaps.getNumSamples() > 0 ) { + // MSAA + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + } else if( chosenCaps.getDoubleBuffered() ) { + // real double buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } else { + // single buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // - SWAP_EVEN + + // 1 - szStep = 2 + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + glad.display(); // - SWAP_EVEN + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize1.oldFront: "+fboFront); + System.out.println("Resize1.nowFront: "+_fboFront); + System.out.println("Resize1.oldBack : "+fboBack); + System.out.println("Resize1.nowBack : "+_fboBack); + Assert.assertEquals(fboFront, _fboFront); + Assert.assertSame(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + Assert.assertSame(fboBack, _fboBack); + + FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + + FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); + System.err.println("Resize1.oldDepth "+depthA); + System.err.println("Resize1.newDepth "+_depth); + Assert.assertNotNull(_depth); + + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + _depth = _fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _color = _fboFront.getColorbuffer(colorA); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + } + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_EVEN + glad.display(); // - SWAP_ODD + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize2.oldFront: "+fboFront); + System.out.println("Resize2.nowFront: "+_fboFront); + System.out.println("Resize2.oldBack : "+fboBack); + System.out.println("Resize2.nowBack : "+_fboBack); + if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { + // real double buffer + Assert.assertEquals(fboBack, _fboFront); + Assert.assertEquals(fboFront, _fboBack); + } else { + // single or MSAA + Assert.assertEquals(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + } + + FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + + FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); // MSAA back w/ depth + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _depth = fboFront.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + + _color = fboBack.getColorbuffer(colorB); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + } + + // 6 + 7 (samples + display) + glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // actual screenshot + + // 8, 9 (resize + samples + display) + szStep = 3; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java deleted file mode 100644 index 7977347a7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLFBODrawableImpl; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.opengl.FBObject; -import com.jogamp.opengl.OffscreenAutoDrawable; -import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.texture.TextureIO; - -public class TestFBODrawableNEWT extends UITestCase { - - static final int widthStep = 800/4; - static final int heightStep = 600/4; - volatile int szStep = 2; - - @Test - public void testGL2ES2_Demo1Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo1MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo2Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); - } - - @Test - public void testGL2ES2_Demo2MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); - } - - @Test - public void testGL2ES2_FBODemoNormal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testEGLES2_Demo0Normal() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - @Test - public void testEGLES2_Demo0MSAA4() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - boolean skipShot = false; - - void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - caps.setFBO(true); - final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); - Assert.assertNotNull(fboDrawable); - Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); - - fboDrawable.setRealized(true); - Assert.assertTrue(fboDrawable.isRealized()); - - final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); - - System.out.println("Realized: "+fboDrawable); - System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); - System.out.println("Realized: "+fbo); - - final GLContext context = fboDrawable.createContext(null); - Assert.assertNotNull(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Post Create-Ctx: "+fbo); - final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(colorA); - final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(depthA); - - final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true); - - glad.addGLEventListener(demo); - glad.addGLEventListener(new GLEventListener() { - volatile int displayCount=0; - volatile int reshapeCount=0; - public void init(GLAutoDrawable drawable) {} - public void dispose(GLAutoDrawable drawable) {} - public void display(GLAutoDrawable drawable) { - final GL gl = drawable.getGL(); - // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); - // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); - // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); - // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); - if(skipShot) { - skipShot=false; - } else { - snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); - } - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - displayCount++; - } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - reshapeCount++; - } - }); - - // 0 - szStep = 2 - glad.display(); - - // 1, 2 (resize + display) - szStep = 1; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - Assert.assertTrue(depthA.equals(_depthA)); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - } - - // 3, 4 (resize + display) - szStep = 4; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - } - - // 5 - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - // 6, 7 (resize + display) - szStep = 3; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - glad.destroy(); - System.out.println("Fin: "+fboDrawable); - - // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java index f7c83a03b..077baad43 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -229,7 +229,7 @@ public class TestFBOMRTNEWT01 extends UITestCase { final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { gl.glFinish(); // sync .. no swap buffers yet! - snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok last_snap_size[0] = ns.getWidth(); last_snap_size[1] = ns.getHeight(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java index b384c9327..b3c542c63 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -106,7 +106,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { if(dw<800) { System.err.println("XXX: "+dw+"x"+dh+", c "+c); if(0 == c%3) { - snapshot(getSimpleTestName("."), i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); + snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); } if( 3 == c ) { new Thread() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java new file mode 100644 index 000000000..3ecf89bfc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -0,0 +1,298 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

+ *

+ * This test simulates shared off-thread GL context / texture usage, + * where the producer use FBOs and delivers shared textures. + * The receiver blends the shared textures onscreen. + * In detail the test consist of: + *

    + *
  • 2 {@link GLOffscreenAutoDrawable.FBO} double buffered + *
      + *
    • each with their own {@link GLContext}, which is shares the {@link GLWindow} one (see below)
    • + *
    • both run within one {@link FPSAnimator} @ 30fps
    • + *
    • produce a texture
    • + *
    • notify the onscreen renderer about new textureID (swapping double buffer)
    • + *
  • + *
  • 1 onscreen {@link GLWindow} + *
      + *
    • shares it's {@link GLContext} w/ above FBOs
    • + *
    • running within one {@link Animator} at v-sync
    • + *
    • uses the shared FBO textures and blends them onscreen
    • + *
  • + *
+ *

+ */ +public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + System.err.println("requested: vsync "+swapInterval+", "+caps); + + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); + if(mainRun) { + glWindow.setSize(512, 512); + } else { + glWindow.setSize(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + final int fbod2_texUnit = 1; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, fbod2_texUnit); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // FBOD2 + final GLOffscreenAutoDrawable.FBO fbod2 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod2.setTextureUnit(fbod2_texUnit); + fbod2.addGLEventListener(new RedSquareES2(-1)); + fbod2.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod2.display(); // init + System.err.println("FBOD2 "+fbod2); + Assert.assertTrue(fbod2.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + if(mainRun) return; + + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + c++; + + if(dw<800) { + System.err.println("XXX: "+dw+"x"+dh+", c "+c); + if(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + fbod1.setSize(width, height); + fbod2.setSize(width, height); + } + }); + + final FPSAnimator animator0 = new FPSAnimator(30); + animator0.add(fbod1); + animator0.add(fbod2); + + final Animator animator1 = new Animator(); + animator1.add(glWindow); + + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + animator0.start(); + animator1.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator0.setUpdateFPSFrames(30, showFPS ? System.err : null); + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration() + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

+ *

+ * This test simulates shared on-thread GL context / texture usage, + * where the producer uses an FBO and delivers a shared texture. + * The receiver draws the shared texture onscreen. + * In detail the test consist of: + *

    + *
  • 1 {@link GLOffscreenAutoDrawable.FBO} double buffered + *
      + * + *
    • running within common {@link Animator} @ 60fps
    • + *
    • produce a texture
    • + *
    • notify the onscreen renderer about new textureID (swapping double buffer)
    • + *
  • + *
  • 1 onscreen {@link GLWindow} + *
      + *
    • shares it's {@link GLContext} w/ above FBO
    • + *
    • running within common {@link Animator} @ 60fps
    • + *
    • uses the shared FBO texture and draws it onscreen
    • + *
  • + *
+ *

+ */ +public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + System.err.println("requested: vsync "+swapInterval+", "+caps); + + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); + if(mainRun) { + glWindow.setSize(512, 512); + } else { + glWindow.setSize(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, 0); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowResized(WindowEvent e) { + fbod1.setSize(glWindow.getWidth(), glWindow.getHeight()); + } + }); + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + if(mainRun) return; + + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + c++; + + if(dw<800) { + System.err.println("XXX: "+dw+"x"+dh+", c "+c); + if(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + final Animator animator1 = new Animator(); + animator1.add(fbod1); + animator1.add(glWindow); + + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + animator1.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration() + * Each test creates a {@link GLDrawable} using the + * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}. + * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}. + *

+ *

+ * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + *

+ */ +public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(widthStep*szStep, heightStep*szStep); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + + @Override + public void windowDestroyNotify(WindowEvent e) { + glad.windowDestroyNotifyOp(); + } + }); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java new file mode 100644 index 000000000..544d74aa5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java @@ -0,0 +1,317 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + *

+ */ +public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep, null); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java new file mode 100644 index 000000000..64a75716b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -0,0 +1,328 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

+ */ +public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(!reqGLCaps.isOnscreen() && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glad); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glad); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..37ec44566 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -0,0 +1,351 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

+ */ +public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.display(); + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java new file mode 100644 index 000000000..47fc99844 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -0,0 +1,300 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

+ */ +public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = offscreenLayer ? + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable) : + GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + + + final NewtCanvasAWT nca = new NewtCanvasAWT(glad); + Assert.assertNotNull(nca); + Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep); + nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + nca.setPreferredSize(size0); + nca.setMinimumSize(size0); + nca.setSize(size0); + + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(nca); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(nca); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.destroy(); + System.out.println("Fin: "+nca); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenLayerAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setPBuffer(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + doTest(true, reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java deleted file mode 100644 index cd1107e25..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLGraphicsConfigurationUtil; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLCapabilities01NEWT extends UITestCase { - static final int width = 100; - static final int height = 100; - - boolean checkProfile(String profile) { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return false; - } - return true; - } - - void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { - System.out.println("Requested GL Caps: "+reqGLCaps); - - final GLCapabilitiesImmutable expGLCaps; - if( GLGraphicsConfigurationUtil.isGLCapabilitiesOffscreenAutoSelection(reqGLCaps) ) { - final GLDrawableFactory f = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - final boolean fboAvailable = true ; // f.canCreateFBO(null, reqGLCaps.getGLProfile()); - final boolean pbufferAvailable = f.canCreateGLPbuffer(null); - expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); - } else { - expGLCaps = reqGLCaps; - } - System.out.println("Expected GL Caps: "+expGLCaps); - // - // Create native windowing resources .. X11/Win/OSX - // - final Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - System.out.println("Window: "+window.getClass().getName()); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - System.out.println("Window Caps Pre_GL: "+chosenCaps); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); - System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - System.out.println("Chosen GL Caps(1): "+chosenGLCaps); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); - Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); - Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); - if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { - // dbl buffer may be disabled w/ offscreen pbuffer and bitmap - Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); - } - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); - System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - drawable.setRealized(false); - window.destroy(); - } - - @Test - public void testAvailableInfo() { - GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - f = GLDrawableFactory.getEGLFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - } - - @Test - public void testGL2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - /** Not implemented ! - @Test - public void testES2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } */ - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLCapabilities01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index cece4c6d5..4c1130498 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -39,13 +39,14 @@ import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -81,14 +82,17 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - GLDrawable drawable = factory.createGLDrawable(window); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); Assert.assertNotNull(drawable); drawable.setRealized(true); Assert.assertTrue(drawable.isRealized()); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) { + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); @@ -104,7 +108,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { } @Override public void windowResized(WindowEvent e) { - glad.windowResizedOp(); + glad.windowResizedOp(window.getWidth(), window.getHeight()); } @Override public void windowDestroyNotify(WindowEvent e) { @@ -123,9 +127,13 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext! GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext! - // create single context using glad1 and assign it to glad1 + // create single context using glad1 and assign it to glad1, + // after destroying the prev. context! { - GLContext singleCtx = glad1.createContext(null); + final GLContext oldCtx = glad1.getContext(); + Assert.assertNotNull(oldCtx); + oldCtx.destroy(); + final GLContext singleCtx = glad1.createContext(null); Assert.assertNotNull(singleCtx); int res = singleCtx.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java deleted file mode 100644 index a6e9cfb07..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GL; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLDrawable01NEWT extends UITestCase { - static final int width = 200, height = 200; - - void doTest(String profile, boolean onscreen, boolean fbo, boolean pbuffer) throws InterruptedException { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return; - } - - final GLProfile glp = GLProfile.get(profile); - final GLCapabilities reqGLCaps = new GLCapabilities(glp); - - reqGLCaps.setOnscreen(onscreen); - reqGLCaps.setPBuffer(!onscreen && pbuffer); - reqGLCaps.setFBO(!onscreen && fbo); - reqGLCaps.setDoubleBuffered(onscreen); - // System.out.println("Requested: "+caps); - - // - // Create native windowing resources .. X11/Win/OSX - // - Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); - // System.out.println("Created: "+window); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - // System.out.println("Pre: "+drawable); - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.getDoubleBuffered()); // offscreen shall be !dbl-buffer - // System.out.println("Post: "+drawable); - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - // System.out.println(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - - // draw something .. - final GL gl = context.getGL(); - gl.glClearColor(1, 1, 1, 1); - gl.glEnable(GL.GL_DEPTH_TEST); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - gl.glViewport(0, 0, width, height); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - drawable.swapBuffers(); - context.release(); - - Thread.sleep(50); - - context.destroy(); - drawable.setRealized(false); - window.destroy(); - // System.out.println("Final: "+window); - } - - @Test - public void testGL2OnScreen() throws InterruptedException { - doTest(GLProfile.GL2, true, false, false); - } - - @Test - public void testES2OnScreen() throws InterruptedException { - doTest(GLProfile.GLES2, true, false, false); - } - - @Test - public void testGL2PBuffer() throws InterruptedException { - doTest(GLProfile.GL2, false, false, true); - } - - @Test - public void testES2PBuffer() throws InterruptedException { - doTest(GLProfile.GLES2, false, false, true); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testGL2FBO() throws InterruptedException { - doTest(GLProfile.GL2, false, true, false); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testES2FBO() throws InterruptedException { - doTest(GLProfile.GLES2, false, true, false); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLDrawable01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java index e4245ef11..d4f3fece5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java @@ -32,14 +32,11 @@ import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import jogamp.opengl.GLDrawableFactoryImpl; @@ -77,13 +74,11 @@ public class TestGLExtensionQueryOffscreen { @Test public void testJogl2ExtensionCheck2() { - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); - GLCapabilitiesChooser glCapsChooser = new DefaultGLCapabilitiesChooser(); - AbstractGraphicsDevice agd = factory.getDefaultDevice(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); - GLAutoDrawable drawable = factory.createGLPbuffer(agd, caps, glCapsChooser, 256, 256, null); - GLContext context = drawable.getContext(); + final GLContext context = drawable.getContext(); context.makeCurrent(); String extensions; try { @@ -94,8 +89,8 @@ public class TestGLExtensionQueryOffscreen { String[] tabExtensions = extensions.split(" "); SortedSet setExtensions = new TreeSet(); Collections.addAll(setExtensions, tabExtensions); - System.out.println("DefaulContext: "+context); - System.out.println("DefaulContext: "+setExtensions); + System.out.println("DefaultContext: "+context); + System.out.println("DefaultContext: "+setExtensions); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java index 33a9b7799..c1b7464e7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java @@ -11,12 +11,14 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; /** * Tests the closing the device of GLWindow and GLPBuffer in JOGL */ +@SuppressWarnings("deprecation") public class TestNEWTCloseX11DisplayBug565 { @Test @@ -59,7 +61,7 @@ public class TestNEWTCloseX11DisplayBug565 { @Test - public void testX11WindowMemoryLeakOffscreenWindow() throws Exception { + public void testX11WindowMemoryLeakGLPbuffer() throws Exception { GLProfile.initSingleton(); // ensure shared resource runner is done try { for ( int j = 0; j < 10; j++ ) { @@ -100,6 +102,48 @@ public class TestNEWTCloseX11DisplayBug565 { } } + @Test + public void testX11WindowMemoryLeakFBOAutoDrawable() throws Exception { + GLProfile.initSingleton(); // ensure shared resource runner is done + try { + for ( int j = 0; j < 10; j++ ) { + final int open0; + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + open0 = X11Util.getOpenDisplayConnectionNumber(); + } else { + open0 = 0; + } + final GLProfile glp = GLProfile.getDefault( ); + GLCapabilitiesImmutable caps = new GLCapabilities( glp ); + + + GLOffscreenAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable( + null, + caps, + new DefaultGLCapabilitiesChooser(), + 256, + 256, + null + ); + buffer.display(); + buffer.destroy(); + + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; + if(openD > 0) { + X11Util.dumpOpenDisplayConnections(); + X11Util.dumpPendingDisplayConnections(); + Assert.assertEquals("New display connection didn't close", 0, openD); + } + } + } + } + catch ( Exception e ) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + public static void main(String args[]) { org.junit.runner.JUnitCore.main(TestNEWTCloseX11DisplayBug565.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java new file mode 100644 index 000000000..d181800c5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java @@ -0,0 +1,236 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +public class TestOffscreenLayer01GLCanvasAWT extends UITestCase { + static boolean useMSAA = false; + static boolean addComp = true; + static int swapInterval = 1; + static boolean shallUseOffscreenPBufferLayer = false; + static boolean noAnimation = false; + static Dimension frameSize0; + static Dimension frameSize1; + static Dimension preferredGLSize; + static long durationPerTest = 1000; + + @BeforeClass + public static void initClass() { + frameSize0 = new Dimension(500,300); + frameSize1 = new Dimension(800,600); + preferredGLSize = new Dimension(400,200); + } + + private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { + + Container c = new Container(); + c.setLayout(new BorderLayout()); + c.add(new Button("north"), BorderLayout.NORTH); + c.add(new Button("south"), BorderLayout.SOUTH); + c.add(new Button("east"), BorderLayout.EAST); + c.add(new Button("west"), BorderLayout.WEST); + c.add(comp, BorderLayout.CENTER); + + f.setLayout(new BorderLayout()); + f.add(new Button("NORTH"), BorderLayout.NORTH); + f.add(new Button("SOUTH"), BorderLayout.SOUTH); + f.add(new Button("EAST"), BorderLayout.EAST); + f.add(new Button("WEST"), BorderLayout.WEST); + f.add(c, BorderLayout.CENTER); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.pack(); + f.validate(); + f.setVisible(true); + }}); + } + + private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { + actrl.stop(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.dispose(); + } } ); + if(null != w) { + w.destroy(); + } + } + + @Test + public void testInfo00() throws InterruptedException, InvocationTargetException { + System.err.println("Java Version: "+Platform.getJavaVersionNumber()); + System.err.println("OS Version: "+Platform.getOSVersionNumber()); + System.err.println("JAWTUtil.isOffscreenLayerRequired(): "+JAWTUtil.isOffscreenLayerRequired()); + System.err.println("JAWTUtil.isOffscreenLayerSupported(): "+JAWTUtil.isOffscreenLayerSupported()); + } + + @Test + public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { + testOffscreenLayerGLCanvas_Impl(true); + } + + private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + final Frame frame1 = new Frame("AWT Parent Frame"); + + GLCapabilities caps = new GLCapabilities(null); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + final GLCanvas glc = new GLCanvas(caps); + glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + glc.setPreferredSize(preferredGLSize); + glc.setMinimumSize(preferredGLSize); + glc.setSize(preferredGLSize); + + GearsES2 demo1 = new GearsES2(swapInterval); + if(noAnimation) { + demo1.setDoRotation(false); + } + glc.addGLEventListener(demo1); + + frame1.setSize(frameSize0); + setupFrameAndShow(frame1, glc); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, + glc.isOffscreenLayerSurfaceEnabled()); + + GLAnimatorControl animator1 = new Animator(glc); + if(!noAnimation) { + animator1.start(); + } + animator1.setUpdateFPSFrames(60, System.err); + + Thread.sleep(durationPerTest/2); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(frameSize1); + frame1.pack(); + frame1.validate(); + }}); + + Thread.sleep(durationPerTest/2); + + end(animator1, frame1, null); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i + * {@link JFrame} . {@link Container}+ . {@link NewtCanvasAWT} . {@link GLWindow} + *

+ *

+ * + Container is the JFrame's implicit root content pane
+ *

+ */ public class TestFocus01SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; @@ -125,6 +135,10 @@ public class TestFocus01SwingAWTRobot extends UITestCase { AWTKeyAdapter buttonKA = new AWTKeyAdapter("Button"); button.addKeyListener(buttonKA); eventCountAdapters.add(buttonKA); + AWTMouseAdapter buttonMA = new AWTMouseAdapter("Button"); + button.addMouseListener(buttonMA); + eventCountAdapters.add(buttonMA); + frame1.getContentPane().add(button, BorderLayout.NORTH); frame1.setSize(width, height); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -158,13 +172,18 @@ public class TestFocus01SwingAWTRobot extends UITestCase { Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); System.err.println("FOCUS AWT Button sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, button, buttonKA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + button, buttonMA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + button, buttonMA); // Request the AWT focus, which should automatically provide the NEWT window with focus. Thread.sleep(100); // allow event sync System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); - Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); + Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); System.err.println("FOCUS NEWT Canvas/GLWindow sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA); Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java index a0efa53ad..d8a9640c1 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java @@ -56,6 +56,15 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +/** + * Testing focus traversal of an AWT component tree with {@link NewtCanvasAWT} attached. + *

+ * {@link JFrame} . {@link JPanel}+ . {@link Container} . {@link NewtCanvasAWT} . {@link GLWindow} + *

+ *

+ * + JPanel is set as JFrame's root content pane
+ *

+ */ public class TestFocus02SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; @@ -85,9 +94,6 @@ public class TestFocus02SwingAWTRobot extends UITestCase { ArrayList eventCountAdapters = new ArrayList(); - /** - * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow - */ GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new GearsES2(); @@ -225,7 +231,9 @@ public class TestFocus02SwingAWTRobot extends UITestCase { System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA); - Assert.assertTrue(AWTRobotUtil.waitForFocusCount(false, newtCanvasAWTFA)); + Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); + Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); Assert.assertEquals(false, buttonNorthOuterFA.focusGained()); Assert.assertEquals(false, jFrame1FA.focusGained()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java index bf72348f9..e03b5e7d6 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java @@ -33,7 +33,6 @@ import org.junit.BeforeClass; import org.junit.Test; import javax.media.nativewindow.*; -import javax.media.nativewindow.util.Point; import com.jogamp.newt.*; import java.io.IOException; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index 473f2f584..f7881615d 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -36,7 +36,7 @@ import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; -class NewtAWTReparentingKeyAdapter extends KeyAdapter { +public class NewtAWTReparentingKeyAdapter extends KeyAdapter { Frame frame; NewtCanvasAWT newtCanvasAWT; GLWindow glWindow; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java deleted file mode 100644 index 4542fa47e..000000000 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.newt.parenting; - -import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Frame; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.awt.GLCanvas; - -import jogamp.nativewindow.jawt.JAWTUtil; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jogamp.common.os.Platform; -import com.jogamp.newt.Window; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; - -public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { - static Dimension frameSize0; - static Dimension frameSize1; - static Dimension preferredGLSize; - static Dimension minGLSize; - static long durationPerTest = 1000; - - @BeforeClass - public static void initClass() { - frameSize0 = new Dimension(500,300); - frameSize1 = new Dimension(800,600); - preferredGLSize = new Dimension(400,200); - minGLSize = new Dimension(200,100); - } - - private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { - - Container c = new Container(); - c.setLayout(new BorderLayout()); - c.add(new Button("north"), BorderLayout.NORTH); - c.add(new Button("south"), BorderLayout.SOUTH); - c.add(new Button("east"), BorderLayout.EAST); - c.add(new Button("west"), BorderLayout.WEST); - c.add(comp, BorderLayout.CENTER); - - f.setLayout(new BorderLayout()); - f.add(new Button("NORTH"), BorderLayout.NORTH); - f.add(new Button("SOUTH"), BorderLayout.SOUTH); - f.add(new Button("EAST"), BorderLayout.EAST); - f.add(new Button("WEST"), BorderLayout.WEST); - f.add(c, BorderLayout.CENTER); - - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - f.validate(); - f.setVisible(true); - }}); - } - private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { - actrl.stop(); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - f.dispose(); - } } ); - if(null != w) { - w.destroy(); - } - } - - @Test - public void testInfo00() throws InterruptedException, InvocationTargetException { - System.err.println("Java Version: "+Platform.getJavaVersionNumber()); - System.err.println("OS Version: "+Platform.getOSVersionNumber()); - System.err.println("JAWTUtil.isOffscreenLayerRequired(): "+JAWTUtil.isOffscreenLayerRequired()); - System.err.println("JAWTUtil.isOffscreenLayerSupported(): "+JAWTUtil.isOffscreenLayerSupported()); - } - - @Test - public void testOnscreenLayerGLCanvas_Onscreen() throws InterruptedException, InvocationTargetException { - testOffscreenLayerGLCanvas_Impl(false); - } - - @Test - public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { - testOffscreenLayerGLCanvas_Impl(true); - } - - private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException { - if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { - System.err.println("onscreen layer n/a"); - return; - } - if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { - System.err.println("offscreen layer n/a"); - return; - } - final Frame frame1 = new Frame("AWT Parent Frame"); - - GLCapabilities glCaps = new GLCapabilities(null); - final GLCanvas glc = new GLCanvas(glCaps); - glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported - glc.setPreferredSize(preferredGLSize); - glc.setMinimumSize(minGLSize); - - GLEventListener demo1 = new GearsES2(1); - glc.addGLEventListener(demo1); - - frame1.setSize(frameSize0); - setupFrameAndShow(frame1, glc); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); - Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, - glc.isOffscreenLayerSurfaceEnabled()); - - GLAnimatorControl animator1 = new Animator(glc); - animator1.start(); - - Thread.sleep(durationPerTest/2); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame1.setSize(frameSize1); - frame1.validate(); - }}); - - Thread.sleep(durationPerTest/2); - - end(animator1, frame1, null); - } - - public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { - Assert.assertNotNull(demo); - Assert.assertNotNull(glWindow); - Window window = glWindow.getDelegatedWindow(); - if(debug) { - MiscUtils.setFieldIfExists(demo, "glDebug", true); - MiscUtils.setFieldIfExists(demo, "glTrace", true); - } - if(!MiscUtils.setFieldIfExists(demo, "window", window)) { - MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); - } - } - - static int atoi(String a) { - int i=0; - try { - i = Integer.parseInt(a); - } catch (Exception ex) { ex.printStackTrace(); } - return i; - } - - public static void main(String args[]) throws IOException { - for(int i=0; ivisible within TIME_OUT diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java index 3f989bfa4..a76b67d57 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java @@ -70,8 +70,8 @@ public class NEWTGLContext { Assert.assertNotNull(window); window.setSize(width, height); window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); GLDrawable drawable = factory.createGLDrawable(window); diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java index c07d5b741..c42d9ff62 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -29,12 +29,14 @@ package com.jogamp.opengl.test.junit.util; import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.util.Iterator; +import java.util.List; import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; import com.jogamp.common.util.locks.SingletonInstance; import com.jogamp.opengl.util.GLReadBufferUtil; @@ -47,6 +49,8 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.Rule; import org.junit.rules.TestName; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.TestClass; public abstract class UITestCase { @@ -58,9 +62,11 @@ public abstract class UITestCase { public static final long SINGLE_INSTANCE_LOCK_TO = 3*60*1000; // wait up to 3 min public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s - static volatile SingletonInstance singletonInstance; + private static volatile SingletonInstance singletonInstance; - static volatile boolean testSupported = true; + private static volatile boolean testSupported = true; + + private static volatile int maxMethodNameLen = 0; private static final synchronized void initSingletonInstance() { if( null == singletonInstance ) { @@ -77,6 +83,20 @@ public abstract class UITestCase { testSupported = v; } + public int getMaxTestNameLen() { + if(0 == maxMethodNameLen) { + int ml = 0; + final TestClass tc = new TestClass(getClass()); + final List testMethods = tc.getAnnotatedMethods(org.junit.Test.class); + for(Iterator iter=testMethods.iterator(); iter.hasNext(); ) { + final int l = iter.next().getName().length(); + if( ml < l ) { ml = l; } + } + maxMethodNameLen = ml; + } + return maxMethodNameLen; + } + public final String getTestMethodName() { return _unitTestName.getMethodName(); } @@ -120,13 +140,12 @@ public abstract class UITestCase { static final String unsupportedTestMsg = "Test not supported on this platform."; /** - * Takes a snapshot of the drawable's current framebuffer. Example filenames: + * Takes a snapshot of the drawable's current front framebuffer. Example filenames: *
-     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png
-     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png
      * 
- * - * @param simpleTestName will be used as the filename prefix * @param sn sequential number * @param postSNDetail optional detail to be added to the filename after sn * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename. @@ -137,30 +156,80 @@ public abstract class UITestCase { * It shall not end with a directory separator, {@link File#separatorChar}. * If null the current working directory is being used. */ - public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { if(null == fileSuffix) { fileSuffix = TextureIO.PNG; } - final StringWriter filenameSW = new StringWriter(); - { + final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; + final String simpleTestName = this.getSimpleTestName("."); + final String filenameBaseName; + { final GLDrawable drawable = gl.getContext().getGLReadDrawable(); final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ; + final String scrnm; + if(caps.isOnscreen()) { + scrnm = "onscreen"; + } else if(caps.isFBO()) { + scrnm = "fbobject"; + } else if(caps.isPBuffer()) { + scrnm = "pbuffer_"; + } else if(caps.isBitmap()) { + scrnm = "bitmap__"; + } else { + scrnm = "unknown_"; + } + final String dblb = caps.getDoubleBuffered() ? "dbl" : "one"; final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_"; final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; - final String aaext = caps.getSampleExtension(); final int samples = caps.getNumSamples() ; + final String aaext = caps.getSampleExtension(); postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; - final PrintWriter pw = new PrintWriter(filenameSW); - pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s", - simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(), - drawable.getWidth(), drawable.getHeight(), fileSuffix); + + filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-S%02d_%s-%04dx%04d.%s", + simpleTestName, sn, postSNDetail, drawable.getGLProfile().getName(), accel, + scrnm, dblb, F_pfmt, pfmt, samples, aaext, + drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_'); } - final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString(); - System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename); + final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName; + System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">"); gl.glFinish(); // just make sure rendering finished .. if(readBufferUtil.readPixels(gl, false)) { readBufferUtil.write(new File(filename)); } - } + } + + public class SnapshotGLEventListener implements GLEventListener { + private final GLReadBufferUtil screenshot; + private volatile boolean makeShot = false; + private volatile int displayCount=0; + private volatile int reshapeCount=0; + public SnapshotGLEventListener(GLReadBufferUtil screenshot) { + this.screenshot = screenshot; + } + public SnapshotGLEventListener() { + this.screenshot = new GLReadBufferUtil(false, false); + } + + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+makeShot); + if(makeShot) { + makeShot=false; + snapshot(displayCount, null, gl, screenshot, TextureIO.PNG, null); + } + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + reshapeCount++; + } + public void setMakeSnapshot() { + makeShot=true; + } + }; + } -- cgit v1.2.3 From 8edaa9780455b60f6034a78970cab4f516d4b061 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 17 Feb 2013 03:25:34 +0100 Subject: NEWT/OSX: Fix Memory Leak ; Fix Occasional Crash Duer to Lifecycle Ops not on Main-Thread. - Fix Memory Leak - NewtWindow::dealloc -> [NewtView release]: Fixes NewtView leak - NewtView::dealloc -> removeTrackingRect: Removes occasional crash (double free of TrackingRect) - Fix Occasional Crash Duer to Lifecycle Ops not on Main-Thread. Perform OSX WindowDriver ops on Main-Thread: - close0 - changeContentView0 - createWindow0 - Cleaned up AddRemove unit tests, added TestAddRemove03GLWindowNEWT --- make/scripts/tests-osx-x64-java7.sh | 1 - make/scripts/tests-osx-x64.sh | 1 - make/scripts/tests.sh | 9 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 43 +++++-- src/newt/native/MacWindow.m | 31 +++-- src/newt/native/NewtMacWindow.m | 32 +++-- .../acore/TestAddRemove01GLCanvasSwingAWT.java | 35 +++--- .../TestAddRemove02GLWindowNewtCanvasAWT.java | 37 +++--- .../jogl/acore/TestAddRemove03GLWindowNEWT.java | 130 +++++++++++++++++++++ .../awt/TestBug664GLCanvasSetVisibleSwingAWT.java | 4 +- 10 files changed, 248 insertions(+), 75 deletions(-) create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/scripts/tests-osx-x64-java7.sh b/make/scripts/tests-osx-x64-java7.sh index 378938167..e1b07202b 100755 --- a/make/scripts/tests-osx-x64-java7.sh +++ b/make/scripts/tests-osx-x64-java7.sh @@ -10,4 +10,3 @@ spath=`dirname $0` . $spath/tests.sh $JAVA_HOME/bin/java -d64 ../build-macosx $* - diff --git a/make/scripts/tests-osx-x64.sh b/make/scripts/tests-osx-x64.sh index 01f3e1bb2..fe2d2c4ec 100755 --- a/make/scripts/tests-osx-x64.sh +++ b/make/scripts/tests-osx-x64.sh @@ -10,4 +10,3 @@ spath=`dirname $0` . $spath/tests.sh /usr/bin/java -d64 ../build-macosx $* - diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 400f3f023..5a7c0f0ec 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -34,8 +34,8 @@ uname -a | grep -i Darwin && MOSX=1 if [ $MOSX -eq 1 ] ; then echo setup OSX environment vars #export NSZombieEnabled=YES - #export NSTraceEvents=YES - #export OBJC_PRINT_EXCEPTIONS=YES + export NSTraceEvents=YES + export OBJC_PRINT_EXCEPTIONS=YES echo NSZombieEnabled $NSZombieEnabled 2>&1 | tee -a java-run.log echo NSTraceEvents $NSTraceEvents 2>&1 | tee -a java-run.log echo OBJC_PRINT_EXCEPTIONS $OBJC_PRINT_EXCEPTIONS 2>&1 | tee -a java-run.log @@ -302,7 +302,8 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove01GLCanvasSwingAWT $* -#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove02GLWindowNewtCanvasAWT $* +testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove02GLWindowNewtCanvasAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove03GLWindowNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* @@ -434,7 +435,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageAWT $* #testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT -testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* +#testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $* diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 5755bdf11..89d53fbeb 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -50,6 +50,7 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.DriverClearFocus; import jogamp.newt.driver.DriverUpdatePosition; +import com.jogamp.common.util.Function; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; @@ -86,7 +87,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = 0; isOffscreenInstance = false; if (0 != handle) { - close0(handle); + OSXUtil.RunOnMainThread(true, new Runnable() { + public void run() { + close0( handle ); + } } ); } } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { @@ -378,24 +382,36 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl try { if(0!=getWindowHandle()) { // save the view .. close the window - surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0); + surfaceHandle = OSXUtil.RunOnMainThread(true, new Function() { + public Long eval(Object... args) { + return Long.valueOf( + changeContentView0(getParentWindowHandle(), getWindowHandle(), 0) ); + } } ).longValue(); if(recreate && 0==surfaceHandle) { throw new NativeWindowException("Internal Error - recreate, window but no view"); } - close0(getWindowHandle()); + OSXUtil.RunOnMainThread(true, new Runnable() { + public void run() { + close0( getWindowHandle() ); + } } ); setWindowHandle(0); } else { surfaceHandle = 0; } - setWindowHandle(createWindow0(getParentWindowHandle(), - pS.getX(), pS.getY(), width, height, - (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), - fullscreen, - ((isUndecorated() || offscreenInstance) ? - NSBorderlessWindowMask : - NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), - NSBackingStoreBuffered, - getScreen().getIndex(), surfaceHandle)); + + setWindowHandle( OSXUtil.RunOnMainThread(true, new Function() { + public Long eval(Object... args) { + return Long.valueOf( + createWindow0( getParentWindowHandle(), + pS.getX(), pS.getY(), width, height, + (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), + fullscreen, + ( (isUndecorated() || offscreenInstance) ? NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask ), + NSBackingStoreBuffered, + getScreen().getIndex(), surfaceHandle) ); + } } ).longValue() ); + if (getWindowHandle() == 0) { throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); } @@ -411,6 +427,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } protected static native boolean initIDs0(); + /** Must be called on Main-Thread */ private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, boolean opaque, boolean fullscreen, int windowStyle, int backingStoreType, @@ -422,9 +439,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** in case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); private native void orderFront0(long window); + /** Must be called on Main-Thread */ private native void close0(long window); private native void setTitle0(long window, String title); private native long contentView0(long window); + /** Must be called on Main-Thread */ private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); private native void setContentSize0(long window, int w, int h); private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index b9c339285..94363624f 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -553,7 +553,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 return (jboolean) res; } -/* +/** + * Method is called on Main-Thread, hence no special invocation required inside method. + * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: createWindow0 * Signature: (JIIIIZIIIJ)J @@ -706,19 +708,10 @@ NS_ENDHANDLER return (jlong) ((intptr_t) myWindow); } -// Footnote: Our view handling produces random 'Assertion failure' even w/o parenting: -// -// [NSThemeFrame lockFocus], /SourceCache/AppKit/AppKit-1138.23/AppKit.subproj/NSView.m:6053 -// [NSThemeFrame(0x7fe94bc72c80) lockFocus] failed with window=0x7fe94bc445a0, windowNumber=9425, [self isHiddenOrHasHiddenAncestor]=0 -// .. -// AppKit 0x00007fff89621001 -[NSView lockFocus] + 250 -// AppKit 0x00007fff8961eafa -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3780 -// AppKit 0x00007fff8961793e -[NSView displayIfNeeded] + 1676 -// AppKit 0x00007fff8961707d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648 -// - -/* +/** + * Method is called on Main-Thread, hence no special invocation required inside method. + * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: close0 * Signature: (J)V @@ -761,8 +754,6 @@ NS_DURING [mView exitFullScreenModeWithOptions: NULL]; } // Note: mWin's release will also release it's mView! - // [mWin setContentView: nil]; - // [mView release]; } NS_HANDLER NS_ENDHANDLER @@ -770,7 +761,8 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; + // [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; + [mWin orderOut: mWin]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -778,7 +770,8 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; + // [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; + [mWin release]; } DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n", @@ -960,7 +953,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 return res; } -/* +/** + * Method is called on Main-Thread, hence no special invocation required inside method. + * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: changeContentView * Signature: (J)J diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 5b826566b..e69f74dfb 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -107,6 +107,7 @@ static jmethodID windowRepaintID = NULL; - (id)initWithFrame:(NSRect)frameRect { + id res = [super initWithFrame:frameRect]; javaWindowObject = NULL; jvmHandle = NULL; @@ -129,28 +130,35 @@ static jmethodID windowRepaintID = NULL; */ myCursor = NULL; - return [super initWithFrame:frameRect]; + DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]); + return res; } - (void) release { + DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]); #ifdef VERBOSE_ON - NSLog(@"NewtView::release\n"); - NSLog(@"%@",[NSThread callStackSymbols]); + // NSLog(@"%@",[NSThread callStackSymbols]); #endif [super release]; } - (void) dealloc { + DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag); if(softLocked) { NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n"); } + if(0 != ptrTrackingTag) { + // [self removeCursorRect: ptrRect cursor: myCursor]; + [self removeTrackingRect: ptrTrackingTag]; + ptrTrackingTag = 0; + } pthread_mutex_destroy(&softLockSync); #ifdef VERBOSE_ON - NSLog(@"NewtView::dealloc\n"); - NSLog(@"%@",[NSThread callStackSymbols]); + //NSLog(@"%@",[NSThread callStackSymbols]); #endif + DBG_PRINT("NewtView::dealloc.X: %p\n", self); [super dealloc]; } @@ -390,25 +398,31 @@ static jmethodID windowRepaintID = NULL; mouseInside = NO; cursorIsHidden = NO; realized = YES; + DBG_PRINT("NewtWindow::create: %p (refcnt %d)\n", res, (int)[res retainCount]); return res; } - (void) release { + DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]); #ifdef VERBOSE_ON - NSLog(@"NewtWindow::release\n"); - NSLog(@"%@",[NSThread callStackSymbols]); + // NSLog(@"%@",[NSThread callStackSymbols]); #endif [super release]; } - (void) dealloc { + DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]); #ifdef VERBOSE_ON - NSLog(@"NewtWindow::dealloc\n"); - NSLog(@"%@",[NSThread callStackSymbols]); + // NSLog(@"%@",[NSThread callStackSymbols]); #endif + NewtView* mView = (NewtView *)[self contentView]; + if( NULL != mView ) { + [mView release]; + } [super dealloc]; + DBG_PRINT("NewtWindow::dealloc.X: %p\n", self); } - (void) setUnrealized diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java index a14364e05..ce8f9adc8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java @@ -50,13 +50,14 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; public class TestAddRemove01GLCanvasSwingAWT extends UITestCase { static long durationPerTest = 50; static int addRemoveCount = 15; - static boolean shallUseOffscreenFBOLayer = false; + static boolean noOnscreenTest = false; + static boolean noOffscreenTest = false; static boolean shallUseOffscreenPBufferLayer = false; static GLProfile glp; static int width, height; @@ -64,8 +65,8 @@ public class TestAddRemove01GLCanvasSwingAWT extends UITestCase { @BeforeClass public static void initClass() { - if(GLProfile.isAvailable(GLProfile.GL2)) { - glp = GLProfile.get(GLProfile.GL2); + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); Assert.assertNotNull(glp); width = 640; height = 480; @@ -139,6 +140,7 @@ public class TestAddRemove01GLCanvasSwingAWT extends UITestCase { { for(int i=0; i Date: Wed, 20 Feb 2013 14:29:04 +0100 Subject: NEWT/OSX: Fix 'locationOnScreen' usage and use proper client-area window screen position (Fixes resize -> position) - Tested w/ NEWT GearsES2 and Java6 and Java7 on OSX --- make/build-test.xml | 5 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 73 ++++++++++----------- src/newt/native/MacWindow.m | 74 +++++++++++----------- src/newt/native/NewtMacWindow.h | 5 +- src/newt/native/NewtMacWindow.m | 21 ++++-- 5 files changed, 95 insertions(+), 83 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/make/build-test.xml b/make/build-test.xml index b3b121049..da6e3ec29 100644 --- a/make/build-test.xml +++ b/make/build-test.xml @@ -300,6 +300,7 @@ + @@ -550,7 +551,6 @@ - @@ -609,15 +609,14 @@ - + - diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 1bbbf8a7d..08c7a14c2 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -144,6 +144,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl setTitle0(getWindowHandle(), title); } + @Override protected void requestFocusImpl(boolean force) { if(!isOffscreenInstance) { requestFocus0(getWindowHandle(), force); @@ -152,6 +153,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } } + @Override public final void clearFocus() { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance); @@ -163,29 +165,34 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } } + @Override public void updatePosition() { - final Point pS = getTopLevelLocationOnScreen(getX(), getY()); + final Point pS = getLocationOnScreenImpl(0, 0); if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS); } if( !isOffscreenInstance ) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); + setWindowClientTopLeftPoint0(getWindowHandle(), pS.getX(), pS.getY()); } // else no offscreen position // no native event (fullscreen, some reparenting) - super.positionChanged(true, getX(), getY()); - } - + positionChanged(true, pS.getX(), pS.getY()); + } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; - final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y); + final PointImmutable pClientLevelOnSreen; + if( isOffscreenInstance ) { + pClientLevelOnSreen = new Point(0, 0); + } else { + pClientLevelOnSreen = new Point(x, y); + } if(DEBUG_IMPLEMENTATION) { final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); final NativeWindow pWin = getParent(); final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null; - System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ + System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+ ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+ ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+ ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+ @@ -207,24 +214,19 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { if(isOffscreenInstance) { - createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false); + createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false); } else { - createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } } - if(x>=0 && y>=0) { + if( width>0 && height>0 && x>=0 && y>=0 ) { if( !isOffscreenInstance ) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); - } // else no offscreen position - // no native event (fullscreen, some reparenting) - super.positionChanged(true, x, y); - } - if(width>0 && height>0) { - if( !isOffscreenInstance ) { - setContentSize0(getWindowHandle(), width, height); + // setContentSize0(getWindowHandle(), width, height); + setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); } // else offscreen size is realized via recreation // no native event (fullscreen, some reparenting) + positionChanged(true, x, y); sizeChanged(true, width, height, false); // incl. validation (incl. repositioning) } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { @@ -237,6 +239,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( !isOffscreenInstance ) { setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); } + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", topPos "+getTopLevelLocationOnScreen(0, 0)+", insets: "+getInsets()); + } return true; } @@ -270,26 +275,22 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // nop - using event driven insetsChange(..) } - @Override - protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(getWidth() != newWidth || getHeight() != newHeight) { - final Point p0S = getTopLevelLocationOnScreen(getX(), getY()); - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); - } - super.sizeChanged(defer, newWidth, newHeight, force); - } - - @Override - protected void positionChanged(boolean defer, int newX, int newY) { + /** Callback for native screen position change event of the client area. */ + protected void screenPositionChanged(boolean defer, int newX, int newY) { // passed coordinates are in screen position of the client area - if(getWindowHandle()!=0) { - // screen position -> window position - Point absPos = new Point(newX, newY); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged (Screen Pos): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); + } + if(getWindowHandle()!=0) { final NativeWindow parent = getParent(); - if(null != parent) { + if(null == parent) { + positionChanged(defer, newX, newY); + } else { + // screen position -> rel child window position + Point absPos = new Point(newX, newY); absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); + positionChanged(defer, absPos.getX(), absPos.getY()); } - super.positionChanged(defer, absPos.getX(), absPos.getY()); } } @@ -433,8 +434,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native long contentView0(long window); /** Must be called on Main-Thread */ private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); - private native void setContentSize0(long window, int w, int h); - private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); + private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h); + private native void setWindowClientTopLeftPoint0(long window, int x, int y); private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 94363624f..1895b98a5 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -62,14 +62,25 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr) return str; } -static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) { - NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)]; +static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y) { + NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]; [mWin setFrameOrigin: pS]; NSView* mView = [mWin contentView]; [mWin invalidateCursorRectsForView: mView]; } +static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height) { + NSSize sz = NSMakeSize(width, height); + NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: sz]; + NSRect rect = { pS, sz }; + [mWin setFrame: rect display:YES]; + + // -> display:YES + // NSView* mView = [mWin contentView]; + // [mWin invalidateCursorRectsForView: mView]; +} + #ifdef VERBOSE_ON static int getRetainCount(NSObject * obj) { return ( NULL == obj ) ? -1 : (int)([obj retainCount]) ; @@ -575,21 +586,21 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow if(screen_idx<0) screen_idx=0; if(screen_idx>=[screens count]) screen_idx=0; NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; - NSRect rect; + NSRect rectWin; if (fullscreen) { styleMask = NSBorderlessWindowMask; - rect = [myScreen frame]; + rectWin = [myScreen frame]; x = 0; y = 0; - w = (jint) (rect.size.width); - h = (jint) (rect.size.height); + w = (jint) (rectWin.size.width); + h = (jint) (rectWin.size.height); } else { - rect = NSMakeRect(x, y, w, h); + rectWin = NSMakeRect(x, y, w, h); } // Allocate the window - NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect + NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType defer: NO @@ -646,7 +657,8 @@ NS_ENDHANDLER // Use given NewtView or allocate an NewtView if NULL if(NULL == myView) { - myView = [[NewtView alloc] initWithFrame: rect] ; + NSRect rectView = NSMakeRect(0, 0, w, h); + myView = [[NewtView alloc] initWithFrame: rectView] ; DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView)); } else { DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView)); @@ -666,7 +678,7 @@ NS_ENDHANDLER } // Immediately re-position the window based on an upper-left coordinate system - setFrameTopLeftPoint(parentWindow, myWindow, x, y); + setWindowClientTopLeftPoint(myWindow, x, y); // force surface creation [myView lockFocus]; @@ -1000,50 +1012,40 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeConten /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setContentSize - * Signature: (JII)V + * Method: setWindowClientTopLeftPointAndSize0 + * Signature: (JIIII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setContentSize0 - (JNIEnv *env, jobject unused, jlong window, jint w, jint h) +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0 + (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) window); + NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); - DBG_PRINT( "setContentSize0 - window: %p (START)\n", win); + DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); - NSSize sz = NSMakeSize(w, h); - [win setContentSize: sz]; + setWindowClientTopLeftPointAndSize(mWin, x, y, w, h); - DBG_PRINT( "setContentSize0 - window: %p (END)\n", win); + DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setFrameTopLeftPoint - * Signature: (JJII)V + * Method: setWindowClientTopLeftPoint0 + * Signature: (JII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setFrameTopLeftPoint0 - (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y) +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0 + (JNIEnv *env, jobject unused, jlong window, jint x, jint y) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); - NSObject *nsParentObj = (NSObject*) ((intptr_t) parent); - NSWindow* pWin = NULL; - if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { - pWin = (NSWindow*) nsParentObj; - } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { - NSView* pView = (NSView*) nsParentObj; - pWin = [pView window]; - } - - DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin); + DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); - setFrameTopLeftPoint(pWin, mWin, x, y); + setWindowClientTopLeftPoint(mWin, x, y); - DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin); + DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); [pool release]; } @@ -1129,6 +1131,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]]; + [mWin setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 1e4f0c3ba..6d1bcca00 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -134,8 +134,9 @@ - (void) attachToParent: (NSWindow*) parent; - (void) detachFromParent: (NSWindow*) parent; -- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p; -- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p; +- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p; +- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz; +- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p; - (NSPoint) getLocationOnScreen: (NSPoint) p; - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 66d68d9d2..282c13fd3 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -356,7 +356,7 @@ static jmethodID windowRepaintID = NULL; sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); @@ -484,19 +484,28 @@ static jmethodID windowRepaintID = NULL; } /** - * p abs screen position w/ top-left origin + * p abs screen position of client-area pos w/ top-left origin, using contentView's client NSSize * returns: abs screen position w/ bottom-left origin */ -- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p +- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p { NSView* mView = [self contentView]; NSRect mViewFrame = [mView frame]; - int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom] + return [self newtAbsClientTLWinPos2AbsBLScreenPos: p size: mViewFrame.size]; +} + +/** + * p abs screen position of client-area pos w/ top-left origin, using given client NSSize + * returns: abs screen position w/ bottom-left origin + */ +- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz +{ + int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom NSScreen* screen = [self screen]; NSRect screenFrame = [screen frame]; - return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0], + return NSMakePoint(screenFrame.origin.x + p.x, screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); } @@ -504,7 +513,7 @@ static jmethodID windowRepaintID = NULL; * p rel client window position w/ top-left origin * returns: abs screen position w/ bottom-left origin */ -- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p +- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p { NSRect winFrame = [self frame]; -- cgit v1.2.3 From 81cbcdc8469143587b2044661dd613c798ae02ba Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 19 Mar 2013 00:33:00 +0100 Subject: OSX/NEWT: Following CALayer streaming design, i.e. issue NSWindow/NSView Ops on main-thread w/o blocking; NEWT/WindowImpl: Volatile multithreaded mutable values Similar to commits: 28c6472335b924080d638b33a28f8f4eedb459b1 f354fb204d8973453c538dda78a2c82c87be61dc main-thread operations cannot block main-thread. Luckily we are able to create the NSWindow and NSView instance uninitialized (deferred) on the current thread, while issuing their initialization on the main-thread w/o blocking. Further more a size glitch is fixed, which didn't take the title bar into account. +++ NEWT/WindowImpl: Volatile multithreaded mutable values Since position, size and other attributes might get changes off-thread, these fields needs to be volatile. --- make/scripts/tests.sh | 6 +- src/newt/classes/jogamp/newt/DefaultEDTUtil.java | 1 + src/newt/classes/jogamp/newt/WindowImpl.java | 17 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 165 +++++++------ src/newt/native/MacWindow.m | 257 ++++++++++++++------- src/newt/native/NewtMacWindow.h | 18 +- src/newt/native/NewtMacWindow.m | 145 +++++++----- 7 files changed, 376 insertions(+), 233 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 8cc3fd84a..71e8ef98d 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -90,6 +90,7 @@ function jrun() { #D_ARGS="-Djogl.debug.GLSLCode" #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL -Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window" + #D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource" #D_ARGS="-Djogl.debug.GLContext.TraceSwitch" #D_ARGS="-Djogl.debug.FixedFuncPipeline -Djogl.debug.GLSLCode" #D_ARGS="-Djogl.debug.FixedFuncPipeline -Djogl.debug.GLSLState" @@ -268,7 +269,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestOlympicES1NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* -#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* +testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* @@ -348,8 +349,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $* -testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $* - +#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index 3c015d3ec..651522799 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -332,6 +332,7 @@ public class DefaultEDTUtil implements EDTUtil { validateNoRecursiveLocksHold(); if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result + System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); task.getThrowable().printStackTrace(); } } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 448b192a2..c01f880fc 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -82,9 +82,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Timeout of queued events (repaint and resize) */ static final long QUEUED_EVENT_TO = 1200; // ms - + + // + // Volatile: Multithread Mutable Access + // private volatile long windowHandle = 0; // lifecycle critical private volatile boolean visible = false; // lifecycle critical + private volatile boolean hasFocus = false; + private volatile int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user + private volatile int x = 64, y = 64; // client-area pos w/o insets + private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated) + private RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock private int surfaceLockCount = 0; // surface lock recursion count @@ -95,12 +103,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private AbstractGraphicsConfiguration config = null; // control access due to delegation protected CapabilitiesImmutable capsRequested = null; protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default - private boolean fullscreen = false, hasFocus = false, brokenFocusChange = false; - private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user - private int x = 64, y = 64; // client-area pos w/o insets + private boolean fullscreen = false, brokenFocusChange = false; private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user) - private Insets insets = new Insets(); // insets of decoration (if top-level && decorated) - + private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets private NativeWindow nfs_parent = null; // non fullscreen parent, in case explicit reparenting is performed (offscreen) private String title = "Newt Window"; diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 6e9335f08..d3a92e023 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -49,7 +49,6 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.DriverClearFocus; import jogamp.newt.driver.DriverUpdatePosition; -import com.jogamp.common.util.Function; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; @@ -86,7 +85,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = 0; isOffscreenInstance = false; if (0 != handle) { - OSXUtil.RunOnMainThread(true, new Runnable() { + OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { close0( handle ); } } ); @@ -101,18 +100,31 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected int lockSurfaceImpl() { - if(!isOffscreenInstance) { - return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; + /** + * if( isOffscreenInstance ) { + * return LOCK_SUCCESS; + * } + */ + final long w = getWindowHandle(); + final long v = surfaceHandle; + if( 0 != v && 0 != w ) { + return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; } - return LOCK_SUCCESS; + return LOCK_SURFACE_NOT_READY; } @Override protected void unlockSurfaceImpl() { - if(!isOffscreenInstance) { - final long h = getWindowHandle(); - if(0 != h) { - unlockSurface0(h); + /** + * if( isOffscreenInstance ) { + * return; + * } + */ + final long w = getWindowHandle(); + final long v = surfaceHandle; + if(0 != w && 0 != v) { + if( !unlockSurface0(w, v) ) { + throw new NativeWindowException("Failed to unlock surface, probably not locked!"); } } } @@ -130,7 +142,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = surfaceHandle; if (isNativeValid()) { if (0 != sscSurfaceHandle) { - orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); } /** this is done by recreation! else if (isVisible()){ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); @@ -172,7 +184,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: updatePosition() -> abs child-client-pos: "+pS); } - setWindowClientTopLeftPoint0(handle, pS.getX(), pS.getY()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPoint0(handle, pS.getX(), pS.getY()); + } } ); // no native event (fullscreen, some reparenting) positionChanged(true, pS.getX(), pS.getY()); } @@ -189,14 +204,17 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: sizeChanged() "+newWidth+"x"+newHeight+" -> abs child-client-pos "+p0S); } - setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY()); + } } ); } } super.sizeChanged(defer, newWidth, newHeight, force); } @Override - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) { final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; final PointImmutable pClientLevelOnSreen; @@ -224,7 +242,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl ", ioi: "+_isOffscreenInstance+ ") -> "+isOffscreenInstance+ "\n\t, "+getReconfigureFlagsAsString(null, flags)); - Thread.dumpStack(); + // Thread.dumpStack(); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { @@ -244,11 +262,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } - } - if( width>0 && height>0 && x>=0 && y>=0 ) { - if( !isOffscreenInstance ) { - // setContentSize0(getWindowHandle(), width, height); - setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + } else if( width>0 && height>0 ) { + if( !isOffscreenInstance ) { + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + } } ); } // else offscreen size is realized via recreation // no native event (fullscreen, some reparenting) positionChanged(true, x, y); @@ -297,19 +316,25 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Callback for native screen position change event of the client area. */ protected void screenPositionChanged(boolean defer, int newX, int newY) { // passed coordinates are in screen position of the client area - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow.positionChanged (Screen Pos): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); - } if(getWindowHandle()!=0) { final NativeWindow parent = getParent(); - if(null == parent) { + if( null == parent || isOffscreenInstance ) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); + } positionChanged(defer, newX, newY); } else { // screen position -> rel child window position Point absPos = new Point(newX, newY); - absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); + Point parentOnScreen = parent.getLocationOnScreen(null); + absPos.translate( parentOnScreen.scale(-1, -1) ); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); + } positionChanged(defer, absPos.getX(), absPos.getY()); } + } else if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } } @@ -383,65 +408,69 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final PointImmutable pS, final int width, final int height, final boolean fullscreen) { - if(0!=getWindowHandle() && !recreate) { + if( 0 != getWindowHandle() && !recreate ) { return; } try { - if(0!=getWindowHandle()) { - // save the view .. close the window - surfaceHandle = OSXUtil.RunOnMainThread(true, new Function() { - public Long eval(Object... args) { - return Long.valueOf( - changeContentView0(getParentWindowHandle(), getWindowHandle(), 0) ); - } } ).longValue(); - if(recreate && 0==surfaceHandle) { - throw new NativeWindowException("Internal Error - recreate, window but no view"); - } - OSXUtil.RunOnMainThread(true, new Runnable() { - public void run() { - close0( getWindowHandle() ); - } } ); + final long parentWin = getParentWindowHandle(); + if( 0 != getWindowHandle() ) { + final long thisWin = getWindowHandle(); setWindowHandle(0); + + if( 0 == surfaceHandle ) { + throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView"); + } + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + changeContentView0(parentWin, thisWin, 0); + close0( thisWin ); + } } ); } else { - surfaceHandle = 0; + if( 0 != surfaceHandle ) { + throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView"); + } + surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen, getScreen().getIndex()); + if( 0 == surfaceHandle ) { + throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); + } } - setWindowHandle( OSXUtil.RunOnMainThread(true, new Function() { - public Long eval(Object... args) { - return Long.valueOf( - createWindow0( getParentWindowHandle(), - pS.getX(), pS.getY(), width, height, - (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), - fullscreen, - ( (isUndecorated() || offscreenInstance) ? NSBorderlessWindowMask : - NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask ), - NSBackingStoreBuffered, - getScreen().getIndex(), surfaceHandle) ); - } } ).longValue() ); - - if (getWindowHandle() == 0) { - throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); - } - surfaceHandle = contentView0(getWindowHandle()); - if( offscreenInstance ) { - orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle()); - } else { - setTitle0(getWindowHandle(), getTitle()); + final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen, + ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask, + NSBackingStoreBuffered, getScreen().getIndex(), surfaceHandle); + if ( newWin == 0 ) { + throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); } + setWindowHandle( newWin ); + + final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; + // Non blocking initialization on main-thread! + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + initWindow0( parentWin, newWin, + pS.getX(), pS.getY(), width, height, + isOpaque, fullscreen, offscreenInstance, getScreen().getIndex(), surfaceHandle); + if( offscreenInstance ) { + orderOut0(0!=parentWin ? parentWin : newWin); + } else { + setTitle0(newWin, getTitle()); + } + } } ); } catch (Exception ie) { ie.printStackTrace(); } } protected static native boolean initIDs0(); + private native long createView0(int x, int y, int w, int h, boolean fullscreen, int screen_idx); + private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, int screen_idx, long view); /** Must be called on Main-Thread */ - private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, int windowStyle, - int backingStoreType, - int screen_idx, long view); - private native boolean lockSurface0(long window); - private native void unlockSurface0(long window); + private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, + boolean opaque, boolean fullscreen, boolean offscreen, int screen_idx, long view); + private native boolean lockSurface0(long window, long view); + private native boolean unlockSurface0(long window, long view); private native void requestFocus0(long window, boolean force); private native void resignFocus0(long window); /** in case of a child window, it actually only issues orderBack(..) */ @@ -452,7 +481,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native void setTitle0(long window, String title); private native long contentView0(long window); /** Must be called on Main-Thread */ - private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); + private native void changeContentView0(long parentWindowOrView, long window, long view); private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h); private native void setWindowClientTopLeftPoint0(long window, int x, int y); private native void setAlwaysOnTop0(long window, boolean atop); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 1895b98a5..db4420b49 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -70,11 +70,18 @@ static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y) { [mWin invalidateCursorRectsForView: mView]; } -static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height) { - NSSize sz = NSMakeSize(width, height); - NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: sz]; - NSRect rect = { pS, sz }; - [mWin setFrame: rect display:YES]; +static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) { + DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d\n", + mWin, (int)x, (int)y, (int)width, (int)height); + NSSize clientSZ = NSMakeSize(width, height); + NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ]; + NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ]; + NSRect rect = { pS, topSZ }; + + DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", + (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); + + [mWin setFrame: rect display:doDisplay]; // -> display:YES // NSView* mView = [mWin contentView]; @@ -88,21 +95,20 @@ static int getRetainCount(NSObject * obj) { #endif static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSView* oldNSView = [win contentView]; - NewtView* oldView = NULL; + NewtView* oldNewtView = NULL; #ifdef VERBOSE_ON int dbgIdx = 1; #endif - if( [oldNSView isMemberOfClass:[NewtView class]] ) { - oldView = (NewtView *) oldNSView; + if( [oldNSView isKindOfClass:[NewtView class]] ) { + oldNewtView = (NewtView *) oldNSView; } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n", - dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView), pview); + dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView), pview); - if(NULL!=oldNSView) { + if( NULL!=oldNSView ) { NS_DURING // Available >= 10.5 - Makes the menubar disapear BOOL iifs; @@ -117,20 +123,20 @@ NS_DURING NS_HANDLER NS_ENDHANDLER DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n", - dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView)); + dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView)); - if( NULL != oldView ) { - jobject globJavaWindowObject = [oldView getJavaWindowObject]; + if( NULL != oldNewtView ) { + jobject globJavaWindowObject = [oldNewtView getJavaWindowObject]; (*env)->DeleteGlobalRef(env, globJavaWindowObject); - [oldView setJavaWindowObject: NULL]; - [oldView setDestroyNotifySent: false]; + [oldNewtView setJavaWindowObject: NULL]; + [oldNewtView setDestroyNotifySent: false]; } [oldNSView removeFromSuperviewWithoutNeedingDisplay]; } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); - if(NULL!=newView) { + if( NULL!=newView ) { jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject); [newView setJavaWindowObject: globJavaWindowObject]; [newView setDestroyNotifySent: false]; @@ -163,12 +169,10 @@ NS_ENDHANDLER dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); // make sure the insets are updated in the java object - [win updateInsets: env]; + [win updateInsets: env jwin:javaWindowObject]; DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n", win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView)); - - [pool release]; } /* @@ -565,29 +569,69 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 } /** - * Method is called on Main-Thread, hence no special invocation required inside method. + * Class: jogamp_newt_driver_macosx_WindowDriver + * Method: createView0 + * Signature: (IIIIZI)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0 + (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, + jboolean fullscreen, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, fs %d, screenidx %d (START)\n", + (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, (int)screen_idx); + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rectWin; + + if (fullscreen) { + rectWin = [myScreen frame]; + x = 0; + y = 0; + w = (jint) (rectWin.size.width); + h = (jint) (rectWin.size.height); + } else { + rectWin = NSMakeRect(x, y, w, h); + } + + NSRect rectView = NSMakeRect(0, 0, w, h); + NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ; + DBG_PRINT( "createView0.X.%d - new view: %p\n", myView); + + [pool release]; + + return (jlong) ((intptr_t) myView); +} + +/** + * Method creates a deferred un-initialized Window, hence no special invocation required inside method. * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: createWindow0 - * Signature: (JIIIIZIIIJ)J + * Signature: (IIIIZIIIJ)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0 - (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask, - jint bufferingType, jint screen_idx, jlong jview) + (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, + jboolean fullscreen, jint styleMask, jint bufferingType, jint screen_idx, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* myView = (NewtView*) (intptr_t) jview ; - DBG_PRINT( "createWindow0 - %p (this), %p (parent), %d/%d %dx%d, opaque %d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen, + DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n", + (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, (int)styleMask, (int)bufferingType, (int)screen_idx, myView); + (void)myView; NSArray *screens = [NSScreen screens]; if(screen_idx<0) screen_idx=0; if(screen_idx>=[screens count]) screen_idx=0; NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; - NSRect rectWin; + NSRect rectWin; if (fullscreen) { styleMask = NSBorderlessWindowMask; rectWin = [myScreen frame]; @@ -603,9 +647,54 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType - defer: NO + defer: YES screen: myScreen isFullscreenWindow: fullscreen]; + + // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]); + + DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]); + + [pool release]; + + return (jlong) ((intptr_t) myWindow); +} + +/** + * Method is called on Main-Thread, hence no special invocation required inside method. + * + * Class: jogamp_newt_driver_macosx_WindowDriver + * Method: initWindow0 + * Signature: (JJIIIIZZZIIJ)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 + (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, + jboolean opaque, jboolean fullscreen, jboolean offscreen, jint screen_idx, jlong jview) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); + NewtView* myView = (NewtView*) (intptr_t) jview ; + + DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, offscreen %d, screenidx %d, view %p (START)\n", + (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen, + (int)offscreen, (int)screen_idx, myView); + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rectWin; + + if (fullscreen) { + rectWin = [myScreen frame]; + x = 0; + y = 0; + w = (jint) (rectWin.size.width); + h = (jint) (rectWin.size.height); + } else { + rectWin = NSMakeRect(x, y, w, h); + } + [myWindow setReleasedWhenClosed: YES]; // default [myWindow setPreservesContentDuringLiveResize: NO]; @@ -615,15 +704,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { parentWindow = (NSWindow*) nsParentObj; parentView = [parentWindow contentView]; - DBG_PRINT( "createWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView); + DBG_PRINT( "initWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView); } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { parentView = (NSView*) nsParentObj; parentWindow = [parentView window]; - DBG_PRINT( "createWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow); + DBG_PRINT( "initWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow); } else { - DBG_PRINT( "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); + DBG_PRINT( "initWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); } - DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]); + DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]); // Remove animations for child windows if(NULL != parentWindow) { @@ -641,11 +730,11 @@ NS_ENDHANDLER #endif if(opaque) { [myWindow setOpaque: YES]; - DBG_PRINT( "createWindow0.%d\n", dbgIdx++); + DBG_PRINT( "initWindow0.%d\n", dbgIdx++); if (!fullscreen) { [myWindow setShowsResizeIndicator: YES]; } - DBG_PRINT( "createWindow0.%d\n", dbgIdx++); + DBG_PRINT( "initWindow0.%d\n", dbgIdx++); } else { [myWindow setOpaque: NO]; [myWindow setBackgroundColor: [NSColor clearColor]]; @@ -653,36 +742,25 @@ NS_ENDHANDLER // specify we want mouse-moved events [myWindow setAcceptsMouseMovedEvents:YES]; - DBG_PRINT( "createWindow0.%d\n", dbgIdx++); - // Use given NewtView or allocate an NewtView if NULL - if(NULL == myView) { - NSRect rectView = NSMakeRect(0, 0, w, h); - myView = [[NewtView alloc] initWithFrame: rectView] ; - DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView)); - } else { - DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView)); - } - - DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); // Set the content view changeContentView(env, jthis, parentView, myWindow, myView); - DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); if(NULL!=parentWindow) { [myWindow attachToParent: parentWindow]; } - // Immediately re-position the window based on an upper-left coordinate system - setWindowClientTopLeftPoint(myWindow, x, y); + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); - // force surface creation - [myView lockFocus]; - [myView unlockFocus]; + // Immediately re-position the window based on an upper-left coordinate system + setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); NS_DURING // concurrent view rendering @@ -696,12 +774,24 @@ NS_DURING NS_HANDLER NS_ENDHANDLER + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + // visible on front - [myWindow orderFront: myWindow]; + if( JNI_FALSE == offscreen ) { + [myWindow orderFront: myWindow]; + } + + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + + // force surface creation + // [myView lockFocus]; + // [myView unlockFocus]; NS_DURING // Available >= 10.5 - Makes the menubar disapear - if(fullscreen) { + if( fullscreen ) { if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { [myView enterFullScreenMode: myScreen withOptions:NULL]; } @@ -713,12 +803,10 @@ NS_ENDHANDLER // right mouse button down events [myView setNextResponder: myWindow]; - DBG_PRINT( "createWindow0 - %p (this), %p (parent): new window: %p, view %p,%d (END)\n", + DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView)); [pool release]; - - return (jlong) ((intptr_t) myWindow); } /** @@ -740,7 +828,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n", mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin); - [mWin setUnrealized]; + [mWin setRealized: NO]; if(NULL!=mView) { // cleanup view @@ -786,8 +874,7 @@ NS_ENDHANDLER [mWin release]; } - DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n", - mWin, getRetainCount(mWin), !destroyNotifySent, mView, getRetainCount(mView), pWin); + DBG_PRINT( "windowClose.Xp\n"); [pool release]; } @@ -795,16 +882,16 @@ NS_ENDHANDLER /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: lockSurface0 - * Signature: (J)Z + * Signature: (JJ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0 - (JNIEnv *env, jclass clazz, jlong window) + (JNIEnv *env, jclass clazz, jlong window, jlong view) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); if(NO == [mWin isRealized]) { return JNI_FALSE; } - NewtView * mView = (NewtView *) [mWin contentView]; + NewtView * mView = (NewtView *) ((intptr_t) view); return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE; /** deadlocks, since we render independent of focus return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */ @@ -813,14 +900,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurfa /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: unlockSurface0 - * Signature: (J)V + * Signature: (JJ)Z */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0 - (JNIEnv *env, jclass clazz, jlong window) +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0 + (JNIEnv *env, jclass clazz, jlong window, jlong view) { - NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - NewtView * mView = (NewtView *) [mWin contentView]; - [mView softUnlock]; + // NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + (void) window; + NewtView * mView = (NewtView *) ((intptr_t) view); + return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE; /** deadlocks, since we render independent of focus [mView unlockFocus]; */ } @@ -946,7 +1034,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0 /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: contentView + * Method: contentView0 * Signature: (J)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 @@ -954,12 +1042,16 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); + NSView* nsView = [win contentView]; + NewtView* newtView = NULL; - DBG_PRINT( "contentView0 - window: %p (START)\n", win); + if( [nsView isKindOfClass:[NewtView class]] ) { + newtView = (NewtView *) nsView; + } - jlong res = (jlong) ((intptr_t) [win contentView]); + DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView); - DBG_PRINT( "contentView0 - window: %p (END)\n", win); + jlong res = (jlong) ((intptr_t) nsView); [pool release]; return res; @@ -970,24 +1062,18 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: changeContentView - * Signature: (J)J + * Signature: (J)V */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0 (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* newView = (NewtView *) ((intptr_t) jview); NewtMacWindow* win = (NewtMacWindow*) ((intptr_t) window); - NSView* oldNSView = [win contentView]; - NewtView* oldView = NULL; - if( [oldNSView isMemberOfClass:[NewtView class]] ) { - oldView = (NewtView *) oldNSView; - } - - DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d (%d) -> %p,%d)\n", - win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView)); + DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n", + win, newView, getRetainCount(newView)); NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView); NSView* pView = NULL; @@ -1002,12 +1088,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeConten changeContentView(env, jthis, pView, win, newView); - DBG_PRINT( "changeContentView0.X - win %p, view (%p,%d (%d) -> %p,%d)\n", - win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView)); + DBG_PRINT( "changeContentView0.X\n"); [pool release]; - - return (jlong) ((intptr_t) oldView); } /* @@ -1023,7 +1106,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClie DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); - setWindowClientTopLeftPointAndSize(mWin, x, y, w, h); + setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, YES); DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 6d1bcca00..09f4a1fd3 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -47,6 +47,8 @@ #define DBG_PRINT(...) #endif +// #define DBG_LIFECYCLE 1 + @interface NewtView : NSView { jobject javaWindowObject; @@ -56,16 +58,19 @@ int jvmVersion; volatile BOOL destroyNotifySent; - volatile BOOL softLocked; + volatile int softLockCount; pthread_mutex_t softLockSync; - NSTrackingRectTag ptrTrackingTag; + volatile NSTrackingRectTag ptrTrackingTag; NSRect ptrRect; NSCursor * myCursor; } - (id)initWithFrame:(NSRect)frameRect; + +#ifdef DBG_LIFECYCLE - (void) release; +#endif - (void) dealloc; /* Set during event dispatching cycle */ @@ -87,7 +92,7 @@ - (BOOL) getDestroyNotifySent; - (BOOL) softLock; -- (void) softUnlock; +- (BOOL) softUnlock; - (BOOL) needsDisplay; - (void) displayIfNeeded; @@ -125,18 +130,21 @@ defer: (BOOL) deferCreation screen:(NSScreen *)screen isFullscreenWindow:(BOOL)isfs; +#ifdef DBG_LIFECYCLE - (void) release; +#endif - (void) dealloc; -- (void) setUnrealized; +- (void) setRealized: (BOOL)v; - (BOOL) isRealized; -- (void) updateInsets: (JNIEnv*) env; +- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin; - (void) attachToParent: (NSWindow*) parent; - (void) detachFromParent: (NSWindow*) parent; - (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p; - (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz; - (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p; +- (NSSize) newtClientSize2TLSize: (NSSize) nsz; - (NSPoint) getLocationOnScreen: (NSPoint) p; - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 282c13fd3..d7b357349 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -113,7 +113,7 @@ static jmethodID windowRepaintID = NULL; jvmHandle = NULL; jvmVersion = 0; destroyNotifySent = NO; - softLocked = NO; + softLockCount = 0; pthread_mutexattr_t softLockSyncAttr; pthread_mutexattr_init(&softLockSyncAttr); @@ -134,19 +134,21 @@ static jmethodID windowRepaintID = NULL; return res; } +#ifdef DBG_LIFECYCLE - (void) release { DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]); -#ifdef VERBOSE_ON - // NSLog(@"%@",[NSThread callStackSymbols]); -#endif [super release]; } +#endif - (void) dealloc { DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag); - if(softLocked) { +#ifdef DBG_LIFECYCLE + NSLog(@"%@",[NSThread callStackSymbols]); +#endif + if( 0 < softLockCount ) { NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n"); } if(0 != ptrTrackingTag) { @@ -155,9 +157,6 @@ static jmethodID windowRepaintID = NULL; ptrTrackingTag = 0; } pthread_mutex_destroy(&softLockSync); -#ifdef VERBOSE_ON - //NSLog(@"%@",[NSThread callStackSymbols]); -#endif DBG_PRINT("NewtView::dealloc.X: %p\n", self); [super dealloc]; } @@ -206,6 +205,7 @@ static jmethodID windowRepaintID = NULL; if(0 != ptrTrackingTag) { // [self removeCursorRect: ptrRect cursor: myCursor]; [self removeTrackingRect: ptrTrackingTag]; + ptrTrackingTag = 0; } ptrRect = [self bounds]; // [self addCursorRect: ptrRect cursor: myCursor]; @@ -230,18 +230,27 @@ static jmethodID windowRepaintID = NULL; - (BOOL) softLock { // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self()); - // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]); - pthread_mutex_lock(&softLockSync); - softLocked = YES; + int err; + if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) { + NSLog(@"NewtView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]); + return NO; + } + softLockCount++; // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self()); - return softLocked; + return 0 < softLockCount; } -- (void) softUnlock +- (BOOL) softUnlock { // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self()); - softLocked = NO; - pthread_mutex_unlock(&softLockSync); + softLockCount--; + int err; + if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) { + softLockCount++; + NSLog(@"NewtView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]); + return NO; + } + return YES; } - (BOOL) needsDisplay @@ -398,25 +407,26 @@ static jmethodID windowRepaintID = NULL; mouseInside = NO; cursorIsHidden = NO; realized = YES; - DBG_PRINT("NewtWindow::create: %p (refcnt %d)\n", res, (int)[res retainCount]); + DBG_PRINT("NewtWindow::create: %p, realized %d (refcnt %d)\n", res, realized, (int)[res retainCount]); return res; } +#ifdef DBG_LIFECYCLE - (void) release { DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]); -#ifdef VERBOSE_ON // NSLog(@"%@",[NSThread callStackSymbols]); -#endif [super release]; } +#endif - (void) dealloc { DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]); -#ifdef VERBOSE_ON - // NSLog(@"%@",[NSThread callStackSymbols]); +#ifdef DBG_LIFECYCLE + NSLog(@"%@",[NSThread callStackSymbols]); #endif + NewtView* mView = (NewtView *)[self contentView]; if( NULL != mView ) { [mView release]; @@ -425,9 +435,9 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("NewtWindow::dealloc.X: %p\n", self); } -- (void) setUnrealized +- (void) setRealized: (BOOL)v { - realized = NO; + realized = v; } - (BOOL) isRealized @@ -435,18 +445,8 @@ static jmethodID windowRepaintID = NULL; return realized; } -- (void) updateInsets: (JNIEnv*) env +- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin { - NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; - } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; - if (env==NULL || javaWindowObject == NULL) { - return; - } - NSRect frameRect = [self frame]; NSRect contentRect = [self contentRectForFrameRect: frameRect]; @@ -460,7 +460,9 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); - (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + if( NULL != env && NULL != javaWin ) { + (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + } } - (void) attachToParent: (NSWindow*) parent @@ -502,11 +504,21 @@ static jmethodID windowRepaintID = NULL; { int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: given %d/%d %dx%d, insets bottom %d -> totalHeight %d\n", + (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight); + NSScreen* screen = [self screen]; NSRect screenFrame = [screen frame]; - return NSMakePoint(screenFrame.origin.x + p.x, - screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n", + (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height); + + NSPoint r = NSMakePoint(screenFrame.origin.x + p.x, + screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); + + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y); + + return r; } /** @@ -524,6 +536,12 @@ static jmethodID windowRepaintID = NULL; winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view } +- (NSSize) newtClientSize2TLSize: (NSSize) nsz +{ + NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom + return topSZ; +} + /** * y-flips input / output * p rel client window position w/ top-left origin @@ -646,7 +664,7 @@ static jint mods2JavaMods(NSUInteger mods) - (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType { NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { + if( ! [nsview isKindOfClass:[NewtView class]] ) { return; } NewtView* view = (NewtView *) nsview; @@ -706,7 +724,7 @@ static jint mods2JavaMods(NSUInteger mods) - (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType { NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { + if( ! [nsview isKindOfClass:[NewtView class]] ) { return; } NewtView* view = (NewtView *) nsview; @@ -783,7 +801,7 @@ static jint mods2JavaMods(NSUInteger mods) { DBG_PRINT( "focusChanged: gained %d\n", gained); NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { + if( ! [nsview isKindOfClass:[NewtView class]] ) { return; } NewtView* view = (NewtView *) nsview; @@ -981,43 +999,42 @@ static jint mods2JavaMods(NSUInteger mods) - (void)windowDidResize: (NSNotification*) notification { - NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; - } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; - if (javaWindowObject == NULL) { - DBG_PRINT("windowDidResize: null javaWindowObject\n"); - return; - } + JNIEnv* env = NULL; + jobject javaWindowObject = NULL; int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); - if(NULL==env) { - DBG_PRINT("windowDidResize: null JNIEnv\n"); - return; + JavaVM *jvmHandle = NULL; + + NSView* nsview = [self contentView]; + if( [nsview isKindOfClass:[NewtView class]] ) { + NewtView* view = (NewtView *) nsview; + javaWindowObject = [view getJavaWindowObject]; + if (javaWindowObject != NULL) { + jvmHandle = [view getJVMHandle]; + env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + } } // update insets on every window resize for lack of better hook place - [self updateInsets: env]; + [self updateInsets: env jwin:javaWindowObject]; - NSRect frameRect = [self frame]; - NSRect contentRect = [self contentRectForFrameRect: frameRect]; + if( NULL != env && NULL != javaWindowObject ) { + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; - (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE, - (jint) contentRect.size.width, - (jint) contentRect.size.height, JNI_FALSE); + (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE, + (jint) contentRect.size.width, + (jint) contentRect.size.height, JNI_FALSE); - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); + if (shallBeDetached) { + (*jvmHandle)->DetachCurrentThread(jvmHandle); + } } } - (void)windowDidMove: (NSNotification*) notification { NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { + if( ! [nsview isKindOfClass:[NewtView class]] ) { return; } NewtView* view = (NewtView *) nsview; @@ -1061,7 +1078,7 @@ static jint mods2JavaMods(NSUInteger mods) [self cursorHide: NO]; NSView* nsview = [self contentView]; - if( ! [nsview isMemberOfClass:[NewtView class]] ) { + if( ! [nsview isKindOfClass:[NewtView class]] ) { return NO; } NewtView* view = (NewtView *) nsview; -- cgit v1.2.3 From 1a1557cd9e31bd7975d858b7b2d49e586805bba4 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 19 Mar 2013 05:27:59 +0100 Subject: OSX/NEWT: NSWindow/NSView Ops on main-thread w/o blocking - Part2 Continues commit 81cbcdc8469143587b2044661dd613c798ae02ba Perform on main-thread invocation from Java, allowing to issue visibleChanged(..) after creation/visible calls. This fixes the 'Visibility not reached ..' regressions. --- .../jogamp/newt/driver/macosx/WindowDriver.java | 112 ++++++++++++++------- src/newt/native/MacWindow.m | 67 ++++++------ 2 files changed, 117 insertions(+), 62 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index d3a92e023..a15c9cded 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -142,23 +142,35 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = surfaceHandle; if (isNativeValid()) { if (0 != sscSurfaceHandle) { - orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } } ); } /** this is done by recreation! else if (isVisible()){ - orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } } ); } */ } } @Override protected void setTitleImpl(final String title) { - setTitle0(getWindowHandle(), title); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setTitle0(getWindowHandle(), title); + } } ); } @Override - protected void requestFocusImpl(boolean force) { + protected void requestFocusImpl(final boolean force) { if(!isOffscreenInstance) { - requestFocus0(getWindowHandle(), force); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + requestFocus0(getWindowHandle(), force); + } } ); } else { focusChanged(false, true); } @@ -170,7 +182,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance); } if(!isOffscreenInstance) { - resignFocus0(getWindowHandle()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + resignFocus0(getWindowHandle()); + } } ); } else { focusChanged(false, false); } @@ -247,41 +262,52 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { if ( !isOffscreenInstance ) { - orderOut0(getWindowHandle()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + orderOut0(getWindowHandle()); + visibleChanged(true, false); + } } ); + } else { + visibleChanged(true, false); } - // no native event .. - visibleChanged(true, false); } if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) || 0 != ( FLAG_CHANGE_DECORATION & flags) || 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { + final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags); if(isOffscreenInstance) { - createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false); + createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false); } else { - createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, + 0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags)); + } + } else { + if( width>0 && height>0 ) { + if( !isOffscreenInstance ) { + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + } } ); + } // else offscreen size is realized via recreation + // no native event (fullscreen, some reparenting) + positionChanged(true, x, y); + sizeChanged(true, width, height, false); + } + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { + if( !isOffscreenInstance ) { + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + orderFront0(getWindowHandle()); + visibleChanged(true, true); + } } ); + } else { + visibleChanged(true, true); + } } - if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } - } else if( width>0 && height>0 ) { if( !isOffscreenInstance ) { - OSXUtil.RunOnMainThread(false, new Runnable() { - public void run() { - setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); - } } ); - } // else offscreen size is realized via recreation - // no native event (fullscreen, some reparenting) - positionChanged(true, x, y); - sizeChanged(true, width, height, false); - } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { - if( !isOffscreenInstance ) { - orderFront0(getWindowHandle()); + setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); } - // no native event .. - visibleChanged(true, true); - } - if( !isOffscreenInstance ) { - setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); } if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets()); @@ -406,11 +432,19 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private void createWindow(final boolean offscreenInstance, final boolean recreate, final PointImmutable pS, final int width, final int height, - final boolean fullscreen) { + final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) { if( 0 != getWindowHandle() && !recreate ) { return; } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+ + ": offscreen "+offscreenInstance+", recreate "+recreate+ + ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+ + ", alwaysOnTop "+alwaysOnTop); + // Thread.dumpStack(); + } try { final long parentWin = getParentWindowHandle(); @@ -451,12 +485,14 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl public void run() { initWindow0( parentWin, newWin, pS.getX(), pS.getY(), width, height, - isOpaque, fullscreen, offscreenInstance, getScreen().getIndex(), surfaceHandle); + isOpaque, fullscreen, visible, offscreenInstance, getScreen().getIndex(), surfaceHandle); if( offscreenInstance ) { orderOut0(0!=parentWin ? parentWin : newWin); } else { setTitle0(newWin, getTitle()); + setAlwaysOnTop0(getWindowHandle(), alwaysOnTop); } + visibleChanged(true, visible); } } ); } catch (Exception ie) { ie.printStackTrace(); @@ -468,22 +504,30 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, int screen_idx, long view); /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, boolean offscreen, int screen_idx, long view); + boolean opaque, boolean fullscreen, boolean visible, boolean offscreen, + int screen_idx, long view); private native boolean lockSurface0(long window, long view); private native boolean unlockSurface0(long window, long view); + /** Must be called on Main-Thread */ private native void requestFocus0(long window, boolean force); + /** Must be called on Main-Thread */ private native void resignFocus0(long window); - /** in case of a child window, it actually only issues orderBack(..) */ + /** Must be called on Main-Thread. In case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); + /** Must be called on Main-Thread */ private native void orderFront0(long window); /** Must be called on Main-Thread */ private native void close0(long window); + /** Must be called on Main-Thread */ private native void setTitle0(long window, String title); private native long contentView0(long window); /** Must be called on Main-Thread */ private native void changeContentView0(long parentWindowOrView, long window, long view); + /** Must be called on Main-Thread */ private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h); + /** Must be called on Main-Thread */ private native void setWindowClientTopLeftPoint0(long window, int x, int y); + /** Must be called on Main-Thread */ private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index db4420b49..e3f4eae34 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -62,30 +62,36 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr) return str; } -static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y) { +static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y, BOOL doDisplay) { + DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay); NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]; + DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y); + [mWin setFrameOrigin: pS]; + DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y); - NSView* mView = [mWin contentView]; - [mWin invalidateCursorRectsForView: mView]; + if( doDisplay ) { + NSView* mView = [mWin contentView]; + [mWin invalidateCursorRectsForView: mView]; + } } static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) { - DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d\n", - mWin, (int)x, (int)y, (int)width, (int)height); + DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay); NSSize clientSZ = NSMakeSize(width, height); NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ]; NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ]; NSRect rect = { pS, topSZ }; - - DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", - (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); + DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); [mWin setFrame: rect display:doDisplay]; + DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); // -> display:YES - // NSView* mView = [mWin contentView]; - // [mWin invalidateCursorRectsForView: mView]; + // if( doDisplay ) { + // NSView* mView = [mWin contentView]; + // [mWin invalidateCursorRectsForView: mView]; + // } } #ifdef VERBOSE_ON @@ -665,19 +671,19 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: initWindow0 - * Signature: (JJIIIIZZZIIJ)V + * Signature: (JJIIIIZZZZIIJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, - jboolean opaque, jboolean fullscreen, jboolean offscreen, jint screen_idx, jlong jview) + jboolean opaque, jboolean fullscreen, jboolean visible, jboolean offscreen, jint screen_idx, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); NewtView* myView = (NewtView*) (intptr_t) jview ; - DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, offscreen %d, screenidx %d, view %p (START)\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen, - (int)offscreen, (int)screen_idx, myView); + DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, offscreen %d, screenidx %d, view %p (START)\n", + (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, + (int) opaque, (int)fullscreen, (int)visible, (int)offscreen, (int)screen_idx, myView); NSArray *screens = [NSScreen screens]; if(screen_idx<0) screen_idx=0; @@ -759,15 +765,22 @@ NS_ENDHANDLER DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); - // Immediately re-position the window based on an upper-left coordinate system + // Immediately re-position this window based on an upper-left coordinate system setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + NS_DURING // concurrent view rendering // Available >= 10.6 - Makes the menubar disapear if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) { [myWindow setAllowsConcurrentViewDrawing: YES]; } + + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { [myView setCanDrawConcurrently: YES]; } @@ -778,7 +791,7 @@ NS_ENDHANDLER dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); // visible on front - if( JNI_FALSE == offscreen ) { + if( JNI_TRUE == visible && JNI_FALSE == offscreen ) { [myWindow orderFront: myWindow]; } @@ -861,7 +874,6 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - // [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; [mWin orderOut: mWin]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", @@ -870,7 +882,6 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - // [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; [mWin release]; } @@ -930,8 +941,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; - [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; - [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + [mWin orderFrontRegardless]; + [mWin makeKeyWindow]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); @@ -954,10 +965,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); if( hasFocus ) { if(NULL != pWin) { - // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO]; - [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + // [mWin makeFirstResponder: pWin]; + [pWin makeKeyWindow]; } else { - [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO]; + [pWin resignKeyWindow]; } } DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); @@ -978,7 +989,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 DBG_PRINT( "orderFront0 - window: %p (START)\n", win); - [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; + [win orderFrontRegardless]; DBG_PRINT( "orderFront0 - window: %p (END)\n", win); @@ -1000,9 +1011,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); if(NULL == pWin) { - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; + [mWin orderOut: mWin]; } else { - [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO]; + [mWin orderBack: mWin]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); @@ -1126,7 +1137,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClie DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); - setWindowClientTopLeftPoint(mWin, x, y); + setWindowClientTopLeftPoint(mWin, x, y, YES); DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); -- cgit v1.2.3 From ec50802db11f897a49a6f9e716186c700411ece5 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 20 Mar 2013 16:15:04 +0100 Subject: OSX/NEWT: Fix native window parenting freeze, invisible/orderOut0, Position bugs w/ parenting Fix native window parenting freeze: - Pull out setJavaWindowObject(..) of changeContentView(..) to be called seperately, add param for changeContentView(..) to enable/disable setJavaWindowObject() - initWindow0(..): - Call changeContentView(..) w/o setJavaWindowObject() - setJavaWindowObject(..) at end of initialization Fix native window parenting orderOut0: If parent window is invisible or no parent used call orderOut(..), otherwise call orderBack(). Fix updatePosition(..): positionChanged(..) - Position bug w/ parenting - AWT parent passed 0/0 - call positionChanged(..) w/ client-pos instead of screen-pos Fix getLocationOnScreenImpl(..) - Position bug w/ parenting - Position < 0/0 is valid! Misc: - setWindowClientTopLeftPointAndSize0(..), setWindowClientTopLeftPoint0(..): Add 'display' param, deciding whether area should be display (invalidated) --- .../newt/awt/event/AWTParentWindowAdapter.java | 2 +- .../jogamp/newt/driver/DriverUpdatePosition.java | 10 ++- .../jogamp/newt/driver/macosx/WindowDriver.java | 66 ++++++++------- src/newt/native/MacWindow.m | 98 +++++++++++++--------- 4 files changed, 101 insertions(+), 75 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index b348220d6..fa494adca 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -115,7 +115,7 @@ public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt } final Window newtWindow = getNewtWindow(); if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) { - ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(); + ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(0, 0); } } diff --git a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java index bb846c081..2ec327187 100644 --- a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java +++ b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java @@ -4,6 +4,12 @@ package jogamp.newt.driver; * Interface tagging driver requirement of absolute positioning, ie. depend on parent position. */ public interface DriverUpdatePosition { - /** Programmatic update the position */ - void updatePosition(); + /** + * Programmatic update the top-left corner + * of the client area relative to it's parent. + * + * @param x x-component + * @param y y-component + **/ + void updatePosition(int x, int y); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index a15c9cded..653e90e3b 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -191,20 +191,25 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } } + private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); } + @Override - public void updatePosition() { + public void updatePosition(int x, int y) { final long handle = getWindowHandle(); if( 0 != handle && !isOffscreenInstance ) { - final Point pS = getLocationOnScreenImpl(0, 0); + final NativeWindow parent = getParent(); + final boolean useParent = useParent(parent); + final int pX=parent.getX(), pY=parent.getY(); + final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent); if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: updatePosition() -> abs child-client-pos: "+pS); + System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos"); } OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { - setWindowClientTopLeftPoint0(handle, pS.getX(), pS.getY()); + setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible()); } } ); // no native event (fullscreen, some reparenting) - positionChanged(true, pS.getX(), pS.getY()); + positionChanged(true, x, y); } } @@ -213,15 +218,16 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final long handle = getWindowHandle(); if( 0 != handle && !isOffscreenInstance ) { final NativeWindow parent = getParent(); - final boolean useParent = null != parent && 0 != parent.getWindowHandle() ; + final boolean useParent = useParent(parent); if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) { - final Point p0S = getLocationOnScreenImpl(0, 0); + final int x=getX(), y=getY(); + final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent); if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: sizeChanged() "+newWidth+"x"+newHeight+" -> abs child-client-pos "+p0S); + System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos"); } OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { - setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY()); + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); } } ); } } @@ -237,9 +243,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl pClientLevelOnSreen = new Point(0, 0); } else { final NativeWindow parent = getParent(); - final boolean useParent = null != parent && 0 != parent.getWindowHandle() ; + final boolean useParent = useParent(parent); if( useParent ) { - pClientLevelOnSreen = getLocationOnScreenImpl(x, y); + pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent); } else { pClientLevelOnSreen = new Point(x, y); } @@ -260,7 +266,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // Thread.dumpStack(); } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { + final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags); + + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) { if ( !isOffscreenInstance ) { OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { @@ -271,13 +279,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl visibleChanged(true, false); } } - if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) || + if( 0 == getWindowHandle() && setVisible || 0 != ( FLAG_CHANGE_DECORATION & flags) || 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags); if(isOffscreenInstance) { - createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false); + createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, false, false); } else { createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags)); @@ -287,14 +294,14 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( !isOffscreenInstance ) { OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { - setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible); } } ); } // else offscreen size is realized via recreation // no native event (fullscreen, some reparenting) positionChanged(true, x, y); sizeChanged(true, width, height, false); } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) { if( !isOffscreenInstance ) { OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { @@ -318,18 +325,18 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected Point getLocationOnScreenImpl(int x, int y) { final NativeWindow parent = getParent(); - final boolean useParent = null != parent && 0 != parent.getWindowHandle() ; + final boolean useParent = useParent(parent); + return getLocationOnScreenImpl(x, y, parent, useParent); + } + private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) { if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) { return OSXUtil.GetLocationOnScreen(surfaceHandle, true, x, y); } final Point p = new Point(x, y); - // min val is 0 - p.setX(Math.max(p.getX(), 0)); - p.setY(Math.max(p.getY(), 0)); if( useParent ) { - p.translate(parent.getLocationOnScreen(null)); + p.translate( parent.getLocationOnScreen(null) ); } return p; } @@ -434,10 +441,6 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final PointImmutable pS, final int width, final int height, final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) { - if( 0 != getWindowHandle() && !recreate ) { - return; - } - if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+ ": offscreen "+offscreenInstance+", recreate "+recreate+ @@ -485,7 +488,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl public void run() { initWindow0( parentWin, newWin, pS.getX(), pS.getY(), width, height, - isOpaque, fullscreen, visible, offscreenInstance, getScreen().getIndex(), surfaceHandle); + isOpaque, fullscreen, visible, getScreen().getIndex(), surfaceHandle); if( offscreenInstance ) { orderOut0(0!=parentWin ? parentWin : newWin); } else { @@ -504,15 +507,14 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, int screen_idx, long view); /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, boolean visible, boolean offscreen, - int screen_idx, long view); + boolean opaque, boolean fullscreen, boolean visible, int screen_idx, long view); private native boolean lockSurface0(long window, long view); private native boolean unlockSurface0(long window, long view); /** Must be called on Main-Thread */ private native void requestFocus0(long window, boolean force); /** Must be called on Main-Thread */ private native void resignFocus0(long window); - /** Must be called on Main-Thread. In case of a child window, it actually only issues orderBack(..) */ + /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */ private native void orderOut0(long window); /** Must be called on Main-Thread */ private native void orderFront0(long window); @@ -524,9 +526,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Must be called on Main-Thread */ private native void changeContentView0(long parentWindowOrView, long window, long view); /** Must be called on Main-Thread */ - private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h); + private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display); /** Must be called on Main-Thread */ - private native void setWindowClientTopLeftPoint0(long window, int x, int y); + private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display); /** Must be called on Main-Thread */ private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index e3f4eae34..c0552216e 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -100,7 +100,36 @@ static int getRetainCount(NSObject * obj) { } #endif -static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) { +static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtView *view, BOOL enable) { + DBG_PRINT( "setJavaWindowObject.0: View %p\n", view); + if( !enable) { + jobject globJavaWindowObject = [view getJavaWindowObject]; + if( NULL != globJavaWindowObject ) { + DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject); + (*env)->DeleteGlobalRef(env, globJavaWindowObject); + [view setJavaWindowObject: NULL]; + } + } else if( NULL != newJavaWindowObject ) { + DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject); + jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject); + [view setJavaWindowObject: globJavaWindowObject]; + { + JavaVM *jvmHandle = NULL; + int jvmVersion = 0; + + if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { + jvmHandle = NULL; + } else { + jvmVersion = (*env)->GetVersion(env); + } + [view setJVMHandle: jvmHandle]; + [view setJVMVersion: jvmVersion]; + } + } + DBG_PRINT( "setJavaWindowObject.X: View %p\n", view); +} + +static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView, BOOL setJavaWindow) { NSView* oldNSView = [win contentView]; NewtView* oldNewtView = NULL; #ifdef VERBOSE_ON @@ -132,10 +161,8 @@ NS_ENDHANDLER dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView)); if( NULL != oldNewtView ) { - jobject globJavaWindowObject = [oldNewtView getJavaWindowObject]; - (*env)->DeleteGlobalRef(env, globJavaWindowObject); - [oldNewtView setJavaWindowObject: NULL]; [oldNewtView setDestroyNotifySent: false]; + setJavaWindowObject(env, NULL, oldNewtView, NO); } [oldNSView removeFromSuperviewWithoutNeedingDisplay]; } @@ -143,20 +170,9 @@ NS_ENDHANDLER dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); if( NULL!=newView ) { - jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject); - [newView setJavaWindowObject: globJavaWindowObject]; [newView setDestroyNotifySent: false]; - { - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } - [newView setJVMHandle: jvmHandle]; - [newView setJVMVersion: jvmVersion]; + if( setJavaWindow ) { + setJavaWindowObject(env, javaWindowObject, newView, YES); } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n", @@ -671,19 +687,19 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: initWindow0 - * Signature: (JJIIIIZZZZIIJ)V + * Signature: (JJIIIIZZZIJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, - jboolean opaque, jboolean fullscreen, jboolean visible, jboolean offscreen, jint screen_idx, jlong jview) + jboolean opaque, jboolean fullscreen, jboolean visible, jint screen_idx, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); NewtView* myView = (NewtView*) (intptr_t) jview ; - DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, offscreen %d, screenidx %d, view %p (START)\n", + DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, screenidx %d, view %p (START)\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, - (int) opaque, (int)fullscreen, (int)visible, (int)offscreen, (int)screen_idx, myView); + (int) opaque, (int)fullscreen, (int)visible, (int)screen_idx, myView); NSArray *screens = [NSScreen screens]; if(screen_idx<0) screen_idx=0; @@ -753,7 +769,7 @@ NS_ENDHANDLER dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); // Set the content view - changeContentView(env, jthis, parentView, myWindow, myView); + changeContentView(env, jthis, parentView, myWindow, myView, NO); DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); @@ -762,8 +778,8 @@ NS_ENDHANDLER [myWindow attachToParent: parentWindow]; } - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d, visible %d\n", + dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible], visible); // Immediately re-position this window based on an upper-left coordinate system setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); @@ -791,7 +807,7 @@ NS_ENDHANDLER dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); // visible on front - if( JNI_TRUE == visible && JNI_FALSE == offscreen ) { + if( visible ) { [myWindow orderFront: myWindow]; } @@ -816,6 +832,12 @@ NS_ENDHANDLER // right mouse button down events [myView setNextResponder: myWindow]; + DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n", + (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView)); + + [myView setDestroyNotifySent: false]; + setJavaWindowObject(env, jthis, myView, YES); + DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView)); @@ -845,13 +867,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 if(NULL!=mView) { // cleanup view - jobject javaWindowObject = [mView getJavaWindowObject]; [mView setDestroyNotifySent: true]; - if(NULL!=javaWindowObject) { - DBG_PRINT( "windowClose.0: Clear global javaWindowObject reference (%p)\n", javaWindowObject); - (*env)->DeleteGlobalRef(env, javaWindowObject); - [mView setJavaWindowObject: NULL]; - } + setJavaWindowObject(env, NULL, mView, NO); } NS_DURING @@ -1007,10 +1024,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) window); NSWindow* pWin = [mWin parentWindow]; + BOOL pWinVisible = NULL != pWin ? [pWin isVisible] : 0; - DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); + DBG_PRINT( "orderOut0 - window: (parent %p visible %d) %p visible %d (START)\n", pWin, pWinVisible, mWin, [mWin isVisible]); - if(NULL == pWin) { + if( NULL == pWin || !pWinVisible ) { [mWin orderOut: mWin]; } else { [mWin orderBack: mWin]; @@ -1097,7 +1115,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContent } } - changeContentView(env, jthis, pView, win, newView); + changeContentView(env, jthis, pView, win, newView, YES); DBG_PRINT( "changeContentView0.X\n"); @@ -1107,17 +1125,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContent /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setWindowClientTopLeftPointAndSize0 - * Signature: (JIIII)V + * Signature: (JIIIIZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0 - (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h) + (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); - setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, YES); + setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display); DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); @@ -1127,17 +1145,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClie /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setWindowClientTopLeftPoint0 - * Signature: (JII)V + * Signature: (JIIZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0 - (JNIEnv *env, jobject unused, jlong window, jint x, jint y) + (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); - setWindowClientTopLeftPoint(mWin, x, y, YES); + setWindowClientTopLeftPoint(mWin, x, y, display); DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); -- cgit v1.2.3 From 6ebf649d1b87944257fe492e0aef842d1b8debc2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 6 May 2013 17:27:09 +0200 Subject: Fix Bug 600 and Bug 721: Adding support for multiple monitors w/ NEWT - Support for all monitor devices and their available modes - X11: Use RandR 1.3 if available - Retrieve information - Changing a monitor device's mode - Support for dedicated and spannig fullscreen - See - TODO: - X11 RandR does _not_ relayout the virtual screen size and neither the CRT's viewport. We may need to relayout them if they were covering a seamless region to achieve same experience! - OSX: No machine to attach a secondary CRT -> TEST! - Tested Manually for Regressions - Linux ARMv6hf (Rasp-Pi/BCM, Panda/X11) - Android (Huawei, Kindle) - Tested Manually and junit: - X11/Linux - NV, ATI-Catalyst w/ 2 CRTs - VBox w/ 4 CRTs - Win/Windows - NV, w/ 2 CRTs - VBox w/ 4 CRTs - X11/OpenIndiana, NV, 1 CRT --- make/build-newt.xml | 1 + make/scripts/java-win64-dbg.bat | 1 + make/scripts/tests-x64.bat | 13 +- make/scripts/tests.sh | 18 +- .../javax/media/nativewindow/util/Dimension.java | 5 + .../javax/media/nativewindow/util/Insets.java | 8 + .../javax/media/nativewindow/util/Point.java | 4 + .../javax/media/nativewindow/util/Rectangle.java | 86 ++- .../nativewindow/util/RectangleImmutable.java | 20 + .../javax/media/nativewindow/util/SurfaceSize.java | 4 +- .../classes/com/jogamp/newt/MonitorDevice.java | 235 ++++++++ src/newt/classes/com/jogamp/newt/MonitorMode.java | 346 ++++++++++++ src/newt/classes/com/jogamp/newt/Screen.java | 93 ++-- src/newt/classes/com/jogamp/newt/ScreenMode.java | 208 ------- src/newt/classes/com/jogamp/newt/Window.java | 38 +- .../com/jogamp/newt/event/MonitorEvent.java | 71 +++ .../com/jogamp/newt/event/MonitorModeListener.java | 37 ++ .../classes/com/jogamp/newt/event/NEWTEvent.java | 7 +- .../classes/com/jogamp/newt/event/OutputEvent.java | 51 ++ .../com/jogamp/newt/event/ScreenModeListener.java | 39 -- .../classes/com/jogamp/newt/opengl/GLWindow.java | 13 + .../classes/com/jogamp/newt/util/MonitorMode.java | 102 ---- .../com/jogamp/newt/util/MonitorModeUtil.java | 247 +++++++++ .../com/jogamp/newt/util/ScreenModeUtil.java | 341 ------------ .../classes/jogamp/newt/MonitorDeviceImpl.java | 147 +++++ src/newt/classes/jogamp/newt/MonitorModeProps.java | 355 ++++++++++++ src/newt/classes/jogamp/newt/OffscreenWindow.java | 13 +- src/newt/classes/jogamp/newt/ScreenImpl.java | 569 ++++++++++---------- src/newt/classes/jogamp/newt/ScreenModeStatus.java | 231 -------- .../classes/jogamp/newt/ScreenMonitorState.java | 195 +++++++ src/newt/classes/jogamp/newt/WindowImpl.java | 201 +++++-- .../jogamp/newt/driver/android/ScreenDriver.java | 99 +++- .../jogamp/newt/driver/android/WindowDriver.java | 16 +- .../jogamp/newt/driver/awt/ScreenDriver.java | 24 +- .../jogamp/newt/driver/bcm/egl/ScreenDriver.java | 56 +- .../jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java | 56 +- .../jogamp/newt/driver/intel/gdl/ScreenDriver.java | 56 +- .../jogamp/newt/driver/kd/ScreenDriver.java | 54 +- .../jogamp/newt/driver/macosx/ScreenDriver.java | 129 ++--- .../jogamp/newt/driver/macosx/WindowDriver.java | 15 +- .../jogamp/newt/driver/windows/ScreenDriver.java | 146 +++-- src/newt/classes/jogamp/newt/driver/x11/RandR.java | 47 +- .../classes/jogamp/newt/driver/x11/RandR11.java | 320 +++++++---- .../classes/jogamp/newt/driver/x11/RandR13.java | 276 +++++++++- .../jogamp/newt/driver/x11/ScreenDriver.java | 146 +++-- src/newt/native/MacWindow.m | 235 ++++---- src/newt/native/NewtMacWindow.h | 1 - src/newt/native/NewtMacWindow.m | 4 +- src/newt/native/ScreenMode.h | 15 +- src/newt/native/Window.h | 17 +- src/newt/native/WindowsWindow.c | 305 ++++++++--- src/newt/native/X11RandR11.c | 44 +- src/newt/native/X11RandR13.c | 597 ++++++++++++--------- src/newt/native/X11Screen.c | 31 +- src/newt/native/X11Screen.h | 1 + src/newt/native/X11Window.c | 18 +- .../opengl/test/android/NEWTElektronActivity.java | 16 +- .../opengl/test/android/NEWTGearsES1Activity.java | 16 +- .../opengl/test/android/NEWTGearsES2Activity.java | 16 +- .../test/android/NEWTGearsES2ActivityLauncher.java | 1 + .../test/android/NEWTGearsES2TransActivity.java | 16 +- .../opengl/test/android/NEWTGraphUI1pActivity.java | 16 +- .../opengl/test/android/NEWTGraphUI2pActivity.java | 16 +- .../test/android/NEWTRedSquareES1Activity.java | 16 +- .../test/android/NEWTRedSquareES2Activity.java | 16 +- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 16 +- .../test/junit/jogl/glsl/TestRulerNEWT01.java | 16 +- .../test/junit/newt/ManualScreenMode03NEWT.java | 32 +- .../test/junit/newt/TestScreenMode00NEWT.java | 119 ++-- .../test/junit/newt/TestScreenMode00bNEWT.java | 24 +- .../test/junit/newt/TestScreenMode01NEWT.java | 133 ++--- .../test/junit/newt/TestScreenMode01aNEWT.java | 212 ++++++++ .../test/junit/newt/TestScreenMode01bNEWT.java | 210 +++++--- .../test/junit/newt/TestScreenMode01cNEWT.java | 249 +++++++++ .../test/junit/newt/TestScreenMode02NEWT.java | 75 +-- 75 files changed, 5159 insertions(+), 2463 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/MonitorDevice.java create mode 100644 src/newt/classes/com/jogamp/newt/MonitorMode.java delete mode 100644 src/newt/classes/com/jogamp/newt/ScreenMode.java create mode 100644 src/newt/classes/com/jogamp/newt/event/MonitorEvent.java create mode 100644 src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java create mode 100644 src/newt/classes/com/jogamp/newt/event/OutputEvent.java delete mode 100644 src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java delete mode 100644 src/newt/classes/com/jogamp/newt/util/MonitorMode.java create mode 100644 src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java delete mode 100644 src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java create mode 100644 src/newt/classes/jogamp/newt/MonitorDeviceImpl.java create mode 100644 src/newt/classes/jogamp/newt/MonitorModeProps.java delete mode 100644 src/newt/classes/jogamp/newt/ScreenModeStatus.java create mode 100644 src/newt/classes/jogamp/newt/ScreenMonitorState.java create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01cNEWT.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/build-newt.xml b/make/build-newt.xml index 862b78422..30c2ddfd1 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -593,6 +593,7 @@ + diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index 8669ba8f8..136fe4667 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -52,6 +52,7 @@ REM set D_ARGS="-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnewt.debug.Display" "-Dnewt.debug.EDT" "-Dnewt.debug.Window" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.debug.EDT" "-Djogl.debug.GLContext" REM set D_ARGS="-Dnewt.debug.Screen" "-Dnewt.debug.EDT" "-Dnativewindow.debug=all" +REM set D_ARGS="-Dnewt.debug.Screen" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true" REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.opengl=true" "-Dsun.awt.noerasebackground=true" diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 0133859fd..27ecfb2cc 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -55,7 +55,7 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestIsReali REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000 @@ -106,10 +106,13 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestFocus01Swin REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.nativewindow.TestRecursiveToolkitLockCORE -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01aNEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT %* +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01cNEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index b53c2f760..c6f69ab74 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -135,6 +135,8 @@ function jrun() { #D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.X11Util" #D_ARGS="-Djogl.debug.GLDrawable" + #D_ARGS="-Dnewt.debug.Screen" + #D_ARGS="-Dnewt.test.Screen.disableRandR13" #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen" #D_ARGS="-Dnewt.debug.Screen -Djogl.debug.Animator" #D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true" @@ -284,7 +286,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $* #testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $* @@ -384,10 +386,12 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00bNEWT #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT -#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT -#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT -#testnoawt com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT -#testnoawt -Djava.awt.headless=true com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT +#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01aNEWT $* +#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT $* +testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01cNEWT $* +#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT $* +#testnoawt com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT $* +#testnoawt -Djava.awt.headless=true com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $* # # awt (testawt) @@ -509,7 +513,9 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* # # Texture / TextureUtils # -#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture01AWT +#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture01AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture02AWT $* + #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGImage00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGImage01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $* diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java index 0a5a94565..4fae98f08 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java @@ -57,7 +57,9 @@ public class Dimension implements Cloneable, DimensionImmutable { } } + @Override public int getWidth() { return width; } + @Override public int getHeight() { return height; } public void setWidth(int width) { @@ -77,10 +79,12 @@ public class Dimension implements Cloneable, DimensionImmutable { return this; } + @Override public String toString() { return new String(width+" x "+height); } + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof Dimension) { @@ -91,6 +95,7 @@ public class Dimension implements Cloneable, DimensionImmutable { return false; } + @Override public int hashCode() { // 31 * x == (x << 5) - x int hash = 31 + width; diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java index 199ec27cb..f22668f55 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java @@ -57,11 +57,17 @@ public class Insets implements Cloneable, InsetsImmutable { } } + @Override public final int getLeftWidth() { return l; } + @Override public final int getRightWidth() { return r; } + @Override public final int getTotalWidth() { return l + r; } + @Override public final int getTopHeight() { return t; } + @Override public final int getBottomHeight() { return b; } + @Override public final int getTotalHeight() { return t + b; } public void setLeftWidth(int left) { l = left; } @@ -69,6 +75,7 @@ public class Insets implements Cloneable, InsetsImmutable { public void setTopHeight(int top) { t = top; } public void setBottomHeight(int bottom) { b = bottom; } + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof Insets) { @@ -79,6 +86,7 @@ public class Insets implements Cloneable, InsetsImmutable { return false; } + @Override public int hashCode() { int sum1 = l + b; int sum2 = t + r; diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java index c53b16928..8e6caf72b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java @@ -54,6 +54,7 @@ public class Point implements Cloneable, PointImmutable { } } + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof Point) { @@ -63,14 +64,17 @@ public class Point implements Cloneable, PointImmutable { return false; } + @Override public final int getX() { return x; } + @Override public final int getY() { return y; } + @Override public int hashCode() { // 31 * x == (x << 5) - x int hash = 31 + x; diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java index 8d6bfe48f..8e6fc8e36 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java @@ -28,6 +28,8 @@ package javax.media.nativewindow.util; +import java.util.List; + public class Rectangle implements Cloneable, RectangleImmutable { int x; int y; @@ -57,15 +59,90 @@ public class Rectangle implements Cloneable, RectangleImmutable { } } + @Override public final int getX() { return x; } + @Override public final int getY() { return y; } + @Override public final int getWidth() { return width; } + @Override public final int getHeight() { return height; } - public void setX(int x) { this.x = x; } - public void setY(int y) { this.y = y; } - public void setWidth(int width) { this.width = width; } - public void setHeight(int height) { this.height = height; } + + public final void setX(int x) { this.x = x; } + public final void setY(int y) { this.y = y; } + public final void setWidth(int width) { this.width = width; } + public final void setHeight(int height) { this.height = height; } + @Override + public final RectangleImmutable union(final RectangleImmutable r) { + return union(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight()); + } + @Override + public final RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2) { + final int x1 = Math.min(x, rx1); + final int y1 = Math.min(y, ry1); + final int x2 = Math.max(x + width, rx2); + final int y2 = Math.max(y + height, ry2); + return new Rectangle(x1, y1, x2 - x1, y2 - y1); + } + /** + * Calculates the union of the given rectangles, stores it in this instance and returns this instance. + * @param rectangles given list of rectangles + * @return this instance holding the union of given rectangles. + */ + public final Rectangle union(final List rectangles) { + int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE; + int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE; + for(int i=rectangles.size()-1; i>=0; i--) { + final RectangleImmutable vp = rectangles.get(i); + x1 = Math.min(x1, vp.getX()); + x2 = Math.max(x2, vp.getX() + vp.getWidth()); + y1 = Math.min(y1, vp.getY()); + y2 = Math.max(y2, vp.getY() + vp.getHeight()); + } + setX(x1); + setY(y1); + setWidth(x2 - x1); + setHeight(y2 - y1); + return this; + } + + @Override + public final RectangleImmutable intersection(RectangleImmutable r) { + return intersection(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight()); + } + @Override + public final RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2) { + final int x1 = Math.max(x, rx1); + final int y1 = Math.max(y, ry1); + final int x2 = Math.min(x + width, rx2); + final int y2 = Math.min(y + height, ry2); + final int ix, iy, iwidth, iheight; + if( x2 < x1 ) { + ix = 0; + iwidth = 0; + } else { + ix = x1; + iwidth = x2 - x1; + } + if( y2 < y1 ) { + iy = 0; + iheight = 0; + } else { + iy = y1; + iheight = y2 - y1; + } + return new Rectangle (ix, iy, iwidth, iheight); + } + @Override + public final float coverage(RectangleImmutable r) { + final RectangleImmutable isect = intersection(r); + final float sqI = (float) ( isect.getWidth()*isect.getHeight() ); + final float sqT = (float) ( width*height ); + return sqI / sqT; + } + + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof Rectangle) { @@ -76,6 +153,7 @@ public class Rectangle implements Cloneable, RectangleImmutable { return false; } + @Override public int hashCode() { int sum1 = x + height; int sum2 = width + y; diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java index d3b43c864..7531989de 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java @@ -41,6 +41,26 @@ public interface RectangleImmutable extends WriteCloneable { int getY(); + /** Returns the union of this rectangle and the given rectangle. */ + RectangleImmutable union(final RectangleImmutable r); + /** Returns the union of this rectangleand the given coordinates. */ + RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2); + /** Returns the intersection of this rectangleand the given rectangle. */ + RectangleImmutable intersection(RectangleImmutable r); + /** Returns the intersection of this rectangleand the given coordinates. */ + RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2); + /** + * Returns the coverage of given rectangle w/ this this one, i.e. between 0.0 and 1.0. + *

+ * Coverage is computed by: + *

+     *    isect = this.intersection(r);
+     *    coverage = area( isect ) / area( this ) ;
+     * 
+ *

+ */ + float coverage(RectangleImmutable r); + /** * Checks whether two rect objects are equal. Two instances * of Rectangle are equal if the four integer values diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java index 8f21bc49b..d7e451af8 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java @@ -36,8 +36,8 @@ package javax.media.nativewindow.util; * */ public class SurfaceSize { - DimensionImmutable resolution; - int bitsPerPixel; + final DimensionImmutable resolution; + final int bitsPerPixel; public SurfaceSize(DimensionImmutable resolution, int bitsPerPixel) { if(null==resolution || bitsPerPixel<=0) { diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java new file mode 100644 index 000000000..fbe4d8cf0 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java @@ -0,0 +1,235 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt; + +import java.util.List; + +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; + +import com.jogamp.common.util.ArrayHashSet; + +/** + * Visual output device, i.e. a CRT, LED ..consisting of it's components:
+ * + *
  • Immutable + *
      + *
    • nativeId
    • + *
    • {@link DimensionImmutable} size in [mm]
    • + *
    • {@link MonitorMode} original mode
    • + *
    • List<MonitorMode> supportedModes
    • + *
  • + *
  • Mutable + *
      + *
    • {@link MonitorMode} current mode
    • + *
    • {@link RectangleImmutable} viewport (rotated)
    • + *
  • + * + */ +public abstract class MonitorDevice { + protected final Screen screen; // backref + protected final int nativeId; // unique monitor device ID + protected final DimensionImmutable sizeMM; // in [mm] + protected final MonitorMode originalMode; + protected final ArrayHashSet supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly! + protected MonitorMode currentMode; + protected boolean modeChanged; + protected Rectangle viewport; + + protected MonitorDevice(Screen screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet supportedModes) { + this.screen = screen; + this.nativeId = nativeId; + this.sizeMM = sizeMM; + this.originalMode = currentMode; + this.supportedModes = supportedModes; + this.currentMode = currentMode; + this.viewport = viewport; + this.modeChanged = false; + } + + /** Returns the {@link Screen} owning this monitor. */ + public final Screen getScreen() { + return screen; + } + + /** + * Tests equality of two MonitorDevice objects + * by evaluating equality of it's components:
    + *
      + *
    • nativeID
    • + *
    + *
    + */ + public final boolean equals(Object obj) { + if (this == obj) { return true; } + if (obj instanceof MonitorDevice) { + MonitorDevice md = (MonitorDevice)obj; + return md.nativeId == nativeId; + } + return false; + } + + /** + * Returns a combined hash code of it's elements:
    + *
      + *
    • nativeID
    • + *
    + */ + public final int hashCode() { + return nativeId; + } + + /** @return the immutable unique native Id of this monitor device. */ + public final int getId() { return nativeId; } + + /** + * @return the immutable monitor size in millimeters. + */ + public final DimensionImmutable getSizeMM() { + return sizeMM; + } + + /** + * Return the immutable original {@link com.jogamp.newt.MonitorMode}, as used at NEWT initialization. + * @return original {@link MonitorMode} which is element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. + */ + public final MonitorMode getOriginalMode() { + return originalMode; + } + + /** + * FIXME: May need to support mutable mode, i.e. adding modes on the fly! + * @return the immutable list of {@link MonitorMode}s supported by this monitor. Use w/ care, it's not a copy! + */ + public final List getSupportedModes() { + return supportedModes.getData(); + } + + /** @return the {@link RectangleImmutable rectangular} portion of the rotated virtual {@link Screen} size represented by this monitor. */ + public final RectangleImmutable getViewport() { + return viewport; + } + + /** Returns true if given coordinates are contained by this {@link #getViewport() viewport}, otherwise false. */ + public final boolean contains(int x, int y) { + return x >= viewport.getX() && + x < viewport.getX() + viewport.getWidth() && + y >= viewport.getY() && + y < viewport.getY() + viewport.getHeight() ; + } + + /** + * Returns the coverage of given rectangle w/ this this {@link #getViewport() viewport}, i.e. between 0.0 and 1.0. + *

    + * Coverage is computed by: + *

    +     *    isect = viewport.intersection(r);
    +     *    coverage = area( isect ) / area( viewport ) ;
    +     * 
    + *

    + */ + public final float coverage(RectangleImmutable r) { + return viewport.coverage(r); + } + + /** + * Returns the union of the given monitor's {@link #getViewport() viewport}. + * @param result storage for result, will be returned + * @param monitors given list of monitors + * @return viewport representing the union of given monitor's viewport. + */ + public static Rectangle unionOfViewports(final Rectangle result, final List monitors) { + int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE; + int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE; + for(int i=monitors.size()-1; i>=0; i--) { + final RectangleImmutable vp = monitors.get(i).getViewport(); + x1 = Math.min(x1, vp.getX()); + x2 = Math.max(x2, vp.getX() + vp.getWidth()); + y1 = Math.min(y1, vp.getY()); + y2 = Math.max(y2, vp.getY() + vp.getHeight()); + } + result.setX(x1); + result.setY(y1); + result.setWidth(x2 - x1); + result.setHeight(y2 - y1); + return result; + } + + public final boolean isOriginalMode() { + return currentMode.hashCode() == originalMode.hashCode(); + } + + /** + * Returns true if the {@link MonitorMode} + * has been changed programmatic via this API only, otherwise false. + *

    + * Note: We cannot guarantee that we won't interfere w/ another running + * application's screen mode change or vice versa. + *

    + */ + public final boolean isModeChangedByUs() { + return modeChanged && !isOriginalMode(); + } + + /** + * Return the current cached {@link MonitorMode} w/o native query. + *

    + * If {@link MonitorMode}s are not supported for this + * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size.

    + * + * @return current {@link MonitorMode} which is element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. + */ + public final MonitorMode getCurrentMode() { + return currentMode; + } + + /** + * Return the current {@link MonitorMode} including a native query. + *

    + * If {@link MonitorMode}s are not supported for this + * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size.

    + * + * @return current {@link MonitorMode} which is element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. + */ + public abstract MonitorMode queryCurrentMode(); + + /** + * Set the current {@link com.jogamp.newt.MonitorMode}. + * @param mode to be made current, must be element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. + * @return true if successful, otherwise false + */ + public abstract boolean setCurrentMode(MonitorMode mode); + + public String toString() { + return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewport+ ", orig "+originalMode+", curr "+currentMode+ + ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]"; + } +} + diff --git a/src/newt/classes/com/jogamp/newt/MonitorMode.java b/src/newt/classes/com/jogamp/newt/MonitorMode.java new file mode 100644 index 000000000..e5b329d47 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/MonitorMode.java @@ -0,0 +1,346 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt; + +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.SurfaceSize; + + +/** Immutable MonitorMode Class, consisting of it's read only components:
    + *
      + *
    • nativeId
    • + *
    • {@link SizeAndRRate}, non rotated surfaceSize and refreshRate
    • + *
    • rotation, measured counter clockwise (CCW)
    • + *
    + * + * Aquire and filter MonitorMode
    + *
      + *
    • A List of read only MonitorModes is being returned by {@link com.jogamp.newt.Screen#getMonitorModes()}.
    • + *
    • You may utilize {@link com.jogamp.newt.util.MonitorModeUtil} to filter and select a desired ScreenMode.
    • + *
    • The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.
    • + *
    • The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.
    • + *
    + *
    + * + * Changing ScreenModes
    + * FIXME!!!!! + *
      + *
    • Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.MonitorMode)}
    • + * to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN) + * {@link com.jogamp.newt.Screen#getFQName()}. + *
    • When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()}) + * is restored.
    • + *
    + *
    + * Example for changing the ScreenMode: + *
    +        // determine target refresh rate
    +        ScreenMode orig = screen.getOriginalScreenMode();
    +        int freq = orig.getOutputMode().getRefreshRate();
    +
    +        // target resolution
    +        Dimension res = new Dimension(800, 600);
    +
    +        // target rotation
    +        int rot = 0;
    +
    +        // filter available ScreenModes
    +        List screenModes = screen.getScreenModes();
    +        screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
    +        screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
    +        screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
    +        screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
    +
    +        // pick 1st one ..
    +        screen.setCurrentScreenMode((ScreenMode) screenModes.get(0)); 
    + * 
    + * + * X11 / AMD just works
    + *
    + * X11 / NVidia difficulties + *
    +    NVidia RANDR RefreshRate Bug
    +        If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
    +        unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
    +        The only way to workaround it is to disable 'DynamicTwinView'.
    +        Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
    +
    +        Check to see if 'DynamicTwinView' is enable:
    +            nvidia-settings -q :0/DynamicTwinview
    +
    +        To disable it (workaround), add the following option to your xorg.conf device section:
    +            Option "DynamicTwinView" "False"
    +
    +    NVidia RANDR Rotation:
    +        To enable it, add the following option to your xorg.conf device section:
    +            Option "RandRRotation" "on"
    + * 
    + * + */ +public class MonitorMode { + /** + * Immutable surfaceSize and refreshRate Class, consisting of it's read only components:
    + *
      + *
    • nativeId
    • + *
    • {@link SurfaceSize} surface memory size
    • + *
    • refresh rate
    • + *
    + */ + public static class SizeAndRRate { + public final SurfaceSize surfaceSize; + public final float refreshRate; + public final int flags; + public final int hashCode; + + public SizeAndRRate(SurfaceSize surfaceSize, float refreshRate, int flags) { + if(null==surfaceSize) { + throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")"); + } + this.surfaceSize=surfaceSize; + this.refreshRate=refreshRate; + this.flags = flags; + this.hashCode = getHashCode(); + } + + private final static String STR_INTERLACE = "Interlace"; + private final static String STR_DOUBLESCAN = "DoubleScan"; + private final static String STR_SEP = ", "; + + public static final StringBuffer flags2String(int flags) { + final StringBuffer sb = new StringBuffer(); + boolean sp = false; + if( 0 != ( flags & FLAG_INTERLACE ) ) { + sb.append(STR_INTERLACE); + sp = true; + } + if( 0 != ( flags & FLAG_DOUBLESCAN ) ) { + if( sp ) { + sb.append(STR_SEP); + } + sb.append(STR_DOUBLESCAN); + sp = true; + } + return sb; + } + public final String toString() { + return new String(surfaceSize+" @ "+refreshRate+" Hz, flags ["+flags2String(flags).toString()+"]"); + } + + /** + * Tests equality of two {@link SizeAndRRate} objects + * by evaluating equality of it's components:
    + *
      + *
    • surfaceSize
    • + *
    • refreshRate
    • + *
    • flags
    • + *
    + */ + public final boolean equals(Object obj) { + if (this == obj) { return true; } + if (obj instanceof SizeAndRRate) { + final SizeAndRRate p = (SizeAndRRate)obj; + return surfaceSize.equals(p.surfaceSize) && + refreshRate == p.refreshRate && + flags == p.flags ; + } + return false; + } + + /** + * Returns a combined hash code of it's elements:
    + *
      + *
    • surfaceSize
    • + *
    • refreshRate
    • + *
    • flags
    • + *
    + */ + public final int hashCode() { + return hashCode; + } + private final int getHashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + surfaceSize.hashCode(); + hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f); + hash = ((hash << 5) - hash) + flags; + return hash; + } + } + + /** zero rotation, compared to normal settings */ + public static final int ROTATE_0 = 0; + + /** 90 degrees CCW rotation */ + public static final int ROTATE_90 = 90; + + /** 180 degrees CCW rotation */ + public static final int ROTATE_180 = 180; + + /** 270 degrees CCW rotation */ + public static final int ROTATE_270 = 270; + + /** Frame is split into two fields. See {@link #getFlags()}. */ + public static final int FLAG_INTERLACE = 1 << 0; + + /** Lines are doubled. See {@link #getFlags()}. */ + public static final int FLAG_DOUBLESCAN = 1 << 1; + + /** The immutable native Id of this instance, which may not be unique. */ + private final int nativeId; + private final SizeAndRRate sizeAndRRate; + private final int rotation; + private final int hashCode; + + public static boolean isRotationValid(int rotation) { + return rotation == MonitorMode.ROTATE_0 || rotation == MonitorMode.ROTATE_90 || + rotation == MonitorMode.ROTATE_180 || rotation == MonitorMode.ROTATE_270 ; + } + + /** + * @param sizeAndRRate the surface size and refresh rate mode + * @param rotation the screen rotation, measured counter clockwise (CCW) + */ + public MonitorMode(int nativeId, SizeAndRRate sizeAndRRate, int rotation) { + if ( !isRotationValid(rotation) ) { + throw new RuntimeException("invalid rotation: "+rotation); + } + this.nativeId = nativeId; + this.sizeAndRRate = sizeAndRRate; + this.rotation = rotation; + this.hashCode = getHashCode(); + } + + /** + * Creates a user instance w/o {@link #getId() identity} to filter our matching modes w/ identity. + *

    + * See {@link com.jogamp.newt.util.MonitorModeUtil} for filter utilities. + *

    + * @param surfaceSize + * @param refreshRate + * @param flags + * @param rotation + */ + public MonitorMode(SurfaceSize surfaceSize, float refreshRate, int flags, int rotation) { + this(0, new SizeAndRRate(surfaceSize, refreshRate, flags), rotation); + } + + /** @return the immutable native Id of this mode, may not be unique, may be 0. */ + public final int getId() { return nativeId; } + + /** Returns the surfaceSize and refreshRate instance. */ + public final SizeAndRRate getSizeAndRRate() { + return sizeAndRRate; + } + + /** Returns the unrotated {@link SurfaceSize} */ + public final SurfaceSize getSurfaceSize() { + return sizeAndRRate.surfaceSize; + } + + public final float getRefreshRate() { + return sizeAndRRate.refreshRate; + } + + /** Returns bitfield w/ flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */ + public final int getFlags() { + return sizeAndRRate.flags; + } + + /** Returns the CCW rotation of this mode */ + public final int getRotation() { + return rotation; + } + + /** Returns the rotated screen width, + * derived from getMonitorMode().getSurfaceSize().getResolution() + * and getRotation() + */ + public final int getRotatedWidth() { + return getRotatedWH(true); + } + + /** Returns the rotated screen height, + * derived from getMonitorMode().getSurfaceSize().getResolution() + * and getRotation() + */ + public final int getRotatedHeight() { + return getRotatedWH(false); + } + + public final String toString() { + return "[Id "+Display.toHexString(nativeId)+", " + sizeAndRRate + ", " + rotation + " degr]"; + } + + /** + * Tests equality of two {@link MonitorMode} objects + * by evaluating equality of it's components:
    + *
      + *
    • nativeId
    • + *
    • sizeAndRRate
    • + *
    • rotation
    • + *
    + */ + public final boolean equals(Object obj) { + if (this == obj) { return true; } + if (obj instanceof MonitorMode) { + MonitorMode sm = (MonitorMode)obj; + return sm.nativeId == this.nativeId && + sm.sizeAndRRate.equals(sizeAndRRate) && + sm.rotation == this.rotation ; + } + return false; + } + + /** + * Returns a combined hash code of it's elements:
    + *
      + *
    • nativeId
    • + *
    • sizeAndRRate
    • + *
    • rotation
    • + *
    + */ + public final int hashCode() { + return hashCode; + } + private final int getHashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + getId(); + hash = ((hash << 5) - hash) + sizeAndRRate.hashCode(); + hash = ((hash << 5) - hash) + getRotation(); + return hash; + } + + private final int getRotatedWH(boolean width) { + final DimensionImmutable d = sizeAndRRate.surfaceSize.getResolution(); + final boolean swap = MonitorMode.ROTATE_90 == rotation || MonitorMode.ROTATE_270 == rotation ; + if ( ( width && swap ) || ( !width && !swap ) ) { + return d.getHeight(); + } + return d.getWidth(); + } +} diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index a09748d52..81a62d898 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -27,14 +27,19 @@ */ package com.jogamp.newt; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorModeListener; import jogamp.newt.Debug; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; +/** + * A screen may span multiple {@link MonitorDevice}s representing their combined virtual size. + */ public abstract class Screen { /** @@ -122,25 +127,30 @@ public abstract class Screen { public abstract int getIndex(); /** - * @return the x position of the virtual top-left origin. + * @return the x position of the virtual viewport's top-left origin. */ public abstract int getX(); /** - * @return the y position of the virtual top-left origin. + * @return the y position of the virtual viewport's top-left origin. */ public abstract int getY(); /** - * @return the rotated virtual width. + * @return the rotated virtual viewport's width. */ public abstract int getWidth(); /** - * @return the rotated virtual height. + * @return the rotated virtual viewport's height. */ public abstract int getHeight(); + /** + * @return the rotated virtual viewport, i.e. origin and size. + */ + public abstract RectangleImmutable getViewport(); + /** * @return the associated Display */ @@ -152,48 +162,68 @@ public abstract class Screen { */ public abstract String getFQName(); - /** - * @param sml ScreenModeListener to be added for ScreenMode change events - */ - public abstract void addScreenModeListener(ScreenModeListener sml); - - /** - * @param sml ScreenModeListener to be removed from ScreenMode change events + /** + * Return a list of all available {@link MonitorMode}s for all {@link MonitorDevice}s. + *

    + * If {@link com.jogamp.newt.MonitorMode ScreenMode}s are not supported for this + * native type {@link com.jogamp.newt.Display#getType()}, it returns a list of size one with the current screen size.

    */ - public abstract void removeScreenModeListener(ScreenModeListener sml); + public abstract List getMonitorModes(); /** - * Return a list of available {@link com.jogamp.newt.ScreenMode ScreenMode}s. + * Return a list of all available {@link MonitorDevice}s. *

    - * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this + * If {@link com.jogamp.newt.MonitorMode ScreenMode}s are not supported for this * native type {@link com.jogamp.newt.Display#getType()}, it returns a list of size one with the current screen size.

    - * - * @return a shallow copy of the internal immutable {@link com.jogamp.newt.ScreenMode ScreenMode}s. */ - public abstract List getScreenModes(); + public abstract List getMonitorDevices(); /** - * Return the original {@link com.jogamp.newt.ScreenMode}, as used at NEWT initialization. - * @return original ScreenMode which is element of the list {@link #getScreenModes()}. + * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport} + * {@link MonitorDevice#coverage(RectangleImmutable) covers} the given rectangle the most. + *

    + * If no coverage is detected the first {@link MonitorDevice} is returned. + *

    */ - public abstract ScreenMode getOriginalScreenMode(); + public final MonitorDevice getMainMonitor(RectangleImmutable r) { + MonitorDevice res = null; + float maxCoverage = Float.MIN_VALUE; + final List monitors = getMonitorDevices(); + for(int i=monitors.size()-1; i>=0; i--) { + final MonitorDevice monitor = monitors.get(i); + final float coverage = monitor.coverage(r); + if( coverage > maxCoverage ) { + maxCoverage = coverage; + res = monitor; + } + } + if( maxCoverage > 0.0f && null != res ) { + return res; + } + return monitors.get(0); + } /** - * Return the current {@link com.jogamp.newt.ScreenMode}. + * Returns the union of all monitor's {@link MonitorDevice#getViewport() viewport}. *

    - * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this - * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size.

    - * - * @return current ScreenMode which is element of the list {@link #getScreenModes()}. + * Should be equal to {@link #getX()}, {@link #getY()}, {@link #getWidth()} and {@link #getHeight()}, + * however, some native toolkits may choose a different virtual screen area. + *

    + * @param result storage for result, will be returned + */ + public final Rectangle unionOfMonitorViewportSize(final Rectangle result) { + return MonitorDevice.unionOfViewports(result, getMonitorDevices()); + } + + /** + * @param sml {@link MonitorModeListener} to be added for {@link MonitorEvent} */ - public abstract ScreenMode getCurrentScreenMode(); + public abstract void addMonitorModeListener(MonitorModeListener sml); /** - * Set the current {@link com.jogamp.newt.ScreenMode}. - * @param screenMode to be made current, must be element of the list {@link #getScreenModes()}. - * @return true if successful, otherwise false + * @param sml {@link MonitorModeListener} to be removed from {@link MonitorEvent} */ - public abstract boolean setCurrentScreenMode(ScreenMode screenMode); + public abstract void removeMonitorModeListener(MonitorModeListener sml); // Global Screens protected static ArrayList screenList = new ArrayList(); @@ -236,6 +266,7 @@ public abstract class Screen { return null; } /** Returns the global display collection */ + @SuppressWarnings("unchecked") public static Collection getAllScreens() { ArrayList list; synchronized(screenList) { diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java deleted file mode 100644 index 1f12217bb..000000000 --- a/src/newt/classes/com/jogamp/newt/ScreenMode.java +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.newt; - -import javax.media.nativewindow.util.DimensionImmutable; - -import com.jogamp.newt.util.MonitorMode; - -/** Immutable ScreenMode Class, consisting of it's read only components:
    - *
      - *
    • {@link com.jogamp.newt.util.MonitorMode}, non rotated values
    • - *
    • rotation, measured counter clockwise (CCW)
    • - *
    - * - * Aquire and filter ScreenModes
    - *
      - *
    • A List of read only ScreenMode's is being returned by {@link com.jogamp.newt.Screen#getScreenModes()}.
    • - *
    • You may utilize {@link com.jogamp.newt.util.ScreenModeUtil} to filter and select a desired ScreenMode.
    • - *
    • The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.
    • - *
    • The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.
    • - *
    - *
    - * - * Changing ScreenModes
    - *
      - *
    • Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.ScreenMode)}
    • - * to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN) - * {@link com.jogamp.newt.Screen#getFQName()}. - *
    • When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()}) - * is restored.
    • - *
    - *
    - * Example for changing the ScreenMode: - *
    -        // determine target refresh rate
    -        ScreenMode orig = screen.getOriginalScreenMode();
    -        int freq = orig.getMonitorMode().getRefreshRate();
    -
    -        // target resolution
    -        Dimension res = new Dimension(800, 600);
    -
    -        // target rotation
    -        int rot = 0;
    -
    -        // filter available ScreenModes
    -        List screenModes = screen.getScreenModes();
    -        screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
    -        screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
    -        screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
    -        screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
    -
    -        // pick 1st one ..
    -        screen.setCurrentScreenMode((ScreenMode) screenModes.get(0)); 
    - * 
    - * - * X11 / AMD just works
    - *
    - * X11 / NVidia difficulties - *
    -    NVidia RANDR RefreshRate Bug
    -        If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
    -        unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
    -        The only way to workaround it is to disable 'DynamicTwinView'.
    -        Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
    -
    -        Check to see if 'DynamicTwinView' is enable:
    -            nvidia-settings -q :0/DynamicTwinview
    -
    -        To disable it (workaround), add the following option to your xorg.conf device section:
    -            Option "DynamicTwinView" "False"
    -
    -    NVidia RANDR Rotation:
    -        To enable it, add the following option to your xorg.conf device section:
    -            Option "RandRRotation" "on"
    - * 
    - * - */ -public class ScreenMode { - /** zero rotation, compared to normal settings */ - public static final int ROTATE_0 = 0; - - /** 90 degrees CCW rotation */ - public static final int ROTATE_90 = 90; - - /** 180 degrees CCW rotation */ - public static final int ROTATE_180 = 180; - - /** 270 degrees CCW rotation */ - public static final int ROTATE_270 = 270; - - MonitorMode monitorMode; - int rotation; - - public static boolean isRotationValid(int rotation) { - return rotation == ScreenMode.ROTATE_0 || rotation == ScreenMode.ROTATE_90 || - rotation == ScreenMode.ROTATE_180 || rotation == ScreenMode.ROTATE_270 ; - } - - /** - * @param monitorMode the monitor mode - * @param rotation the screen rotation, measured counter clockwise (CCW) - */ - public ScreenMode(MonitorMode monitorMode, int rotation) { - if ( !isRotationValid(rotation) ) { - throw new RuntimeException("invalid rotation: "+rotation); - } - this.monitorMode = monitorMode; - this.rotation = rotation; - } - - /** Returns the unrotated MonitorMode */ - public final MonitorMode getMonitorMode() { - return monitorMode; - } - - /** Returns the CCW rotation of this mode */ - public final int getRotation() { - return rotation; - } - - /** Returns the rotated screen width, - * derived from getMonitorMode().getSurfaceSize().getResolution() - * and getRotation() - */ - public final int getRotatedWidth() { - return getRotatedWH(true); - } - - /** Returns the rotated screen height, - * derived from getMonitorMode().getSurfaceSize().getResolution() - * and getRotation() - */ - public final int getRotatedHeight() { - return getRotatedWH(false); - } - - public final String toString() { - return "[ " + getMonitorMode() + ", " + rotation + " degr ]"; - } - - /** - * Tests equality of two ScreenMode objects - * by evaluating equality of it's components:
    - *
      - *
    • monitorMode
    • - *
    • rotation
    • - *
    - *
    - */ - public final boolean equals(Object obj) { - if (this == obj) { return true; } - if (obj instanceof ScreenMode) { - ScreenMode sm = (ScreenMode)obj; - return sm.getMonitorMode().equals(getMonitorMode()) && - sm.getRotation() == this.getRotation() ; - } - return false; - } - - /** - * Returns a combined hash code of it's elements:
    - *
      - *
    • monitorMode
    • - *
    • rotation
    • - *
    - */ - public final int hashCode() { - // 31 * x == (x << 5) - x - int hash = 31 + getMonitorMode().hashCode(); - hash = ((hash << 5) - hash) + getRotation(); - return hash; - } - - private final int getRotatedWH(boolean width) { - final DimensionImmutable d = getMonitorMode().getSurfaceSize().getResolution(); - final boolean swap = ScreenMode.ROTATE_90 == rotation || ScreenMode.ROTATE_270 == rotation ; - if ( ( width && swap ) || ( !width && !swap ) ) { - return d.getHeight(); - } - return d.getWidth(); - } -} diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index ab1eef308..0bebf330a 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -28,6 +28,8 @@ package com.jogamp.newt; +import java.util.List; + import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.event.KeyListener; @@ -41,6 +43,7 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.util.RectangleImmutable; /** * Specifying NEWT's Window functionality: @@ -80,10 +83,19 @@ public interface Window extends NativeWindow, WindowClosingProtocol { boolean isNativeValid(); /** - * @return The associated Screen + * @return The associated {@link Screen} */ Screen getScreen(); + /** + * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport} + * {@link MonitorDevice#coverage(RectangleImmutable) covers} this window the most. + *

    + * If no coverage is detected the first {@link MonitorDevice} is returned. + *

    + */ + MonitorDevice getMainMonitor(); + /** * Set the CapabilitiesChooser to help determine the native visual type. * @@ -344,8 +356,32 @@ public interface Window extends NativeWindow, WindowClosingProtocol { ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate); + /** + * Enable or disable fullscreen mode for this window. + *

    + * Fullscreen mode is established on the {@link #getMainMonitor() main monitor}. + *

    + * @param fullscreen enable or disable fullscreen mode + * @return success + * @see #setFullscreen(List) + * @see #isFullscreen() + */ boolean setFullscreen(boolean fullscreen); + /** + * Enable fullscreen mode for this window spanning across the given {@link MonitorDevice}s + * or across all {@link MonitorDevice}s. + *

    + * Disable fullscreen via {@link #setFullscreen(boolean)}. + *

    + * @param monitors if null fullscreen will be spanned across all {@link MonitorDevice}s, + * otherwise across the given list of {@link MonitorDevice}. + * @return success + * @see #setFullscreen(boolean) + * @see #isFullscreen() + */ + boolean setFullscreen(List monitors); + boolean isFullscreen(); static interface FocusRunnable { diff --git a/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java new file mode 100644 index 000000000..c47936a7a --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java @@ -0,0 +1,71 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt.event; + +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; + +@SuppressWarnings("serial") +public class MonitorEvent extends OutputEvent { + public static final short EVENT_MONITOR_MODE_CHANGE_NOTIFY = 600; + public static final short EVENT_MONITOR_MODE_CHANGED = 601; + + private final MonitorMode mode; + + public MonitorEvent (short eventType, MonitorDevice source, long when, MonitorMode mode) { + super(eventType, source, when); + this.mode = mode; + } + + /** Returns the {@link #getSource() source}, which is a {@link MonitorDevice}. */ + public final MonitorDevice getMonitor() { return (MonitorDevice)source; } + + public final MonitorMode getMode() { return mode; } + + public static String getEventTypeString(short type) { + switch(type) { + case EVENT_MONITOR_MODE_CHANGE_NOTIFY: return "EVENT_MONITOR_MODE_CHANGE_NOTIFY"; + case EVENT_MONITOR_MODE_CHANGED: return "EVENT_MONITOR_MODE_CHANGED"; + default: return "unknown (" + type + ")"; + } + } + + public final String toString() { + return toString(null).toString(); + } + + public final StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + sb.append("MonitorEvent[").append(getEventTypeString(getEventType())).append(", source ").append(source) + .append(", mode ").append(mode).append(", "); + return super.toString(sb).append("]"); + } +} diff --git a/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java new file mode 100644 index 000000000..11e23def1 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java @@ -0,0 +1,37 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt.event; + +public interface MonitorModeListener { + /** called before the monitor mode will be changed */ + void monitorModeChangeNotify(MonitorEvent me); + + /** called after the monitor mode has been changed */ + void monitorModeChanged(MonitorEvent me, boolean success); +} diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index ea96f634f..c1bc791d8 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -41,9 +41,10 @@ package com.jogamp.newt.event; * * Event type registry:
    *
      - *
    • WindowEvent 100..10x
    • - *
    • MouseEvent 200..20x
    • - *
    • KeyEvent 300..30x
    • + *
    • WindowEvent 100..10x
    • + *
    • MouseEvent 200..20x
    • + *
    • KeyEvent 300..30x
    • + *
    • MonitorEvent 600..60x
    • *

    */ @SuppressWarnings("serial") diff --git a/src/newt/classes/com/jogamp/newt/event/OutputEvent.java b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java new file mode 100644 index 000000000..86fa95877 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java @@ -0,0 +1,51 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt.event; + +@SuppressWarnings("serial") +public abstract class OutputEvent extends NEWTEvent +{ + protected OutputEvent(short eventType, Object source, long when) { + super(eventType, source, when); + } + + /** + public String toString() { + return toString(null).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + sb.append("OutputEvent["); + super.toString(sb).append("]"); + return sb; + } */ +} diff --git a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java b/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java deleted file mode 100644 index 7bca23cfe..000000000 --- a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.newt.event; - -import com.jogamp.newt.ScreenMode; - -public interface ScreenModeListener { - /** called before the screen mode will be changed */ - void screenModeChangeNotify(ScreenMode sm); - - /** called after the screen mode has been changed */ - void screenModeChanged(ScreenMode sm, boolean success); -} diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index de62747be..1500d48e6 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -34,6 +34,8 @@ package com.jogamp.newt.opengl; +import java.util.List; + import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; @@ -64,6 +66,7 @@ import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; @@ -224,6 +227,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return window.getScreen(); } + @Override + public final MonitorDevice getMainMonitor() { + return window.getMainMonitor(); + } + @Override public final void setTitle(String title) { window.setTitle(title); @@ -341,6 +349,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind public final boolean setFullscreen(boolean fullscreen) { return window.setFullscreen(fullscreen); } + + @Override + public boolean setFullscreen(List monitors) { + return window.setFullscreen(monitors); + } @Override public final boolean isFullscreen() { diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java deleted file mode 100644 index 8104f207a..000000000 --- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.newt.util; - -import javax.media.nativewindow.util.*; - -/** Immutable MonitorMode Class, consisting of it's read only components:
    - *
      - *
    • {@link javax.media.nativewindow.util.SurfaceSize} surface memory size
    • - *
    • {@link javax.media.nativewindow.util.DimensionImmutable} size in [mm]
    • - *
    • refresh rate
    • - *
    - */ -public class MonitorMode { - SurfaceSize surfaceSize; - DimensionImmutable screenSizeMM; // in [mm] - int refreshRate; - - public MonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int refreshRate) { - // Don't validate screenSizeMM and refreshRate, since they may not be supported by the OS - if(null==surfaceSize) { - throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")"); - } - this.surfaceSize=surfaceSize; - this.screenSizeMM=screenSizeMM; - this.refreshRate=refreshRate; - } - - public final SurfaceSize getSurfaceSize() { - return surfaceSize; - } - - public final DimensionImmutable getScreenSizeMM() { - return screenSizeMM; - } - - public final int getRefreshRate() { - return refreshRate; - } - - public final String toString() { - return new String("[ "+surfaceSize+" x "+refreshRate+" Hz, "+screenSizeMM+" mm ]"); - } - - /** - * Checks whether two size objects are equal. Two instances - * of MonitorMode are equal if the three components - * surfaceSize and refreshRate - * are equal. screenSizeMM is kept out intentional to reduce the requirements for finding the current mode. - * @return true if the two dimensions are equal; - * otherwise false. - */ - public final boolean equals(Object obj) { - if (this == obj) { return true; } - if (obj instanceof MonitorMode) { - MonitorMode p = (MonitorMode)obj; - return getSurfaceSize().equals(p.getSurfaceSize()) && - /* getScreenSizeMM().equals(p.getScreenSizeMM()) && */ - getRefreshRate() == p.getRefreshRate() ; - } - return false; - } - - /** - * returns a hash code over surfaceSize and refreshRate. - * screenSizeMM is kept out intentional to reduce the requirements for finding the current mode. - */ - public final int hashCode() { - // 31 * x == (x << 5) - x - int hash = 31 + getSurfaceSize().hashCode(); - /* hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); */ - hash = ((hash << 5) - hash) + getRefreshRate(); - return hash; - } -} - diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java new file mode 100644 index 000000000..16ffe754f --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java @@ -0,0 +1,247 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.newt.util; + +import com.jogamp.newt.MonitorMode; + +import java.util.ArrayList; +import java.util.List; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.SurfaceSize; + +/** + * Convenient {@link com.jogamp.newt.MonitorMode} utility methods, + * filters etc. + */ +public class MonitorModeUtil { + + public static int getIndex(List monitorModes, MonitorMode search) { + return monitorModes.indexOf(search); + } + + public static int getIndexByHashCode(List monitorModes, MonitorMode search) { + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; i monitorModes, MonitorMode.SizeAndRRate sizeAndRate, int modeId, int rotation) { + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; i filterBySurfaceSize(List monitorModes, SurfaceSize surfaceSize) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; null!=monitorModes && i filterByRotation(List monitorModes, int rotation) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; null!=monitorModes && i filterByBpp(List monitorModes, int bitsPerPixel) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; null!=monitorModes && i filterByFlags(List monitorModes, int flags) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; null!=monitorModes && i filterByResolution(List monitorModes, DimensionImmutable resolution) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + final int resolution_sq = resolution.getHeight()*resolution.getWidth(); + int mode_dsq=Integer.MAX_VALUE, mode_dsq_idx=0; + + for (int i=0; null!=monitorModes && i filterByRate(List monitorModes, float refreshRate) { + final List out = new ArrayList(); + if( null!=monitorModes && monitorModes.size()>0 ) { + float mode_dr = Float.MAX_VALUE; + int mode_dr_idx = -1; + for (int i=0; null!=monitorModes && i getHighestAvailableBpp(List monitorModes) { + if( null!=monitorModes && monitorModes.size()>0 ) { + int highest = -1; + for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) { + final MonitorMode mode = monitorModes.get(i); + final int bpp = mode.getSurfaceSize().getBitsPerPixel(); + if (bpp > highest) { + highest = bpp; + } + } + return filterByBpp(monitorModes, highest); + } + return new ArrayList(); + } + + /** + * + * @param monitorModes + * @return modes with highest available refresh rate. May return zero sized list for non. + */ + public static List getHighestAvailableRate(List monitorModes) { + if( null!=monitorModes && monitorModes.size()>0 ) { + float highest = -1; + for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) { + final MonitorMode mode = monitorModes.get(i); + final float rate = mode.getRefreshRate(); + if (rate > highest) { + highest = rate; + } + } + return filterByRate(monitorModes, highest); + } + return new ArrayList(); + } + +} diff --git a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java deleted file mode 100644 index 93797c5fb..000000000 --- a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.newt.util; - -import com.jogamp.common.util.ArrayHashSet; -import com.jogamp.newt.ScreenMode; -import java.util.ArrayList; -import java.util.List; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.SurfaceSize; - -/** - * Convenient {@link com.jogamp.newt.ScreenMode} utility methods, - * filters etc. - */ -public class ScreenModeUtil { - /** WARNING: must be synchronized with ScreenMode.h, native implementation - * 2: width and height - */ - public static final int NUM_RESOLUTION_PROPERTIES = 2; - - /** WARNING: must be synchronized with ScreenMode.h, native implementation - * 1: bpp - */ - public static final int NUM_SURFACE_SIZE_PROPERTIES = 1; - - /** WARNING: must be synchronized with ScreenMode.h, native implementation - * 3: ScreenSizeMM[width, height], refresh-rate - */ - public static final int NUM_MONITOR_MODE_PROPERTIES = 3; - - /** WARNING: must be synchronized with ScreenMode.h, native implementation - * 1: rotation, native_mode_id - */ - public static final int NUM_SCREEN_MODE_PROPERTIES = 1; - - /** WARNING: must be synchronized with ScreenMode.h, native implementation - * count + all the above - */ - public static final int NUM_SCREEN_MODE_PROPERTIES_ALL = 8; - - public static int getIndex(List screenModes, ScreenMode search) { - return screenModes.indexOf(search); - } - - public static int getIndexByHashCode(List screenModes, ScreenMode search) { - for (int i=0; null!=screenModes && i filterByResolution(List screenModes, DimensionImmutable resolution) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - List out = new ArrayList(); - int resolution_sq = resolution.getHeight()*resolution.getWidth(); - int sm_dsq=resolution_sq, sm_dsq_idx=0; - - for (int i=0; null!=screenModes && i0) { - return out; - } - // nearest .. - resolution = screenModes.get(sm_dsq_idx).getMonitorMode().getSurfaceSize().getResolution(); - return filterByResolution(screenModes, resolution); - } - - public static List filterBySurfaceSize(List screenModes, SurfaceSize surfaceSize) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - List out = new ArrayList(); - for (int i=0; null!=screenModes && i0 ? out : null; - } - - public static List filterByRotation(List screenModes, int rotation) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - List out = new ArrayList(); - for (int i=0; null!=screenModes && i0 ? out : null; - } - - public static List filterByBpp(List screenModes, int bitsPerPixel) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - List out = new ArrayList(); - for (int i=0; null!=screenModes && i0 ? out : null; - } - - /** - * - * @param screenModes - * @param refreshRate - * @return modes with nearest refreshRate, or matching ones - */ - public static List filterByRate(List screenModes, int refreshRate) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - int sm_dr = refreshRate; - int sm_dr_idx = -1; - List out = new ArrayList(); - for (int i=0; null!=screenModes && i0) { - return out; - } - refreshRate = screenModes.get(sm_dr_idx).getMonitorMode().getRefreshRate(); - return filterByRate(screenModes, refreshRate); - } - - public static List getHighestAvailableBpp(List screenModes) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - int highest = -1; - for (int i=0; null!=screenModes && i < screenModes.size(); i++) { - ScreenMode sm = screenModes.get(i); - int bpp = sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(); - if (bpp > highest) { - highest = bpp; - } - } - return filterByBpp(screenModes, highest); - } - - public static List getHighestAvailableRate(List screenModes) { - if(null==screenModes || screenModes.size()==0) { - return null; - } - int highest = -1; - for (int i=0; null!=screenModes && i < screenModes.size(); i++) { - ScreenMode sm = screenModes.get(i); - int rate = sm.getMonitorMode().getRefreshRate(); - if (rate > highest) { - highest = rate; - } - } - return filterByRate(screenModes, highest); - } - - /** WARNING: must be synchronized with ScreenMode.h, native implementation */ - public static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) { - Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]); - return resolution; - } - - /** WARNING: must be synchronized with ScreenMode.h, native implementation */ - public static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) { - SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]); - return surfaceSize; - } - - /** WARNING: must be synchronized with ScreenMode.h, native implementation */ - public static MonitorMode streamInMonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int[] monitorProperties, int offset) { - int refreshRate = monitorProperties[offset++]; - return new MonitorMode(surfaceSize, screenSizeMM, refreshRate); - } - - /** WARNING: must be synchronized with ScreenMode.h, native implementation */ - public static ScreenMode streamInScreenMode(MonitorMode monitorMode, int[] modeProperties, int offset) { - int rotation = modeProperties[offset++]; - return new ScreenMode(monitorMode, rotation); - } - - /** - * WARNING: must be synchronized with ScreenMode.h, native implementation - * - * @param modeProperties the input data - * @param offset the offset to the input data - * @return ScreenMode element matching the input modeProperties, - * or null if input could not be processed. - */ - public static ScreenMode streamIn(int[] modeProperties, int offset) { - return streamInImpl(null, null, null, null, null, modeProperties, offset); - } - - /** - * WARNING: must be synchronized with ScreenMode.h, native implementation - * - * @param resolutionPool hash array of unique resolutions, no duplicates - * @param surfaceSizePool hash array of unique SurfaceSize, no duplicates - * @param monitorModePool hash array of unique MonitorMode, no duplicates - * @param screenModePool hash array of unique ScreenMode, no duplicates - * @param modeProperties the input data - * @param offset the offset to the input data - * @return index of the identical (old or new) ScreenMode element in screenModePool, - * matching the input modeProperties, or -1 if input could not be processed. - */ - public static int streamIn(ArrayHashSet resolutionPool, - ArrayHashSet surfaceSizePool, - ArrayHashSet screenSizeMMPool, - ArrayHashSet monitorModePool, - ArrayHashSet screenModePool, - int[] modeProperties, int offset) { - ScreenMode screenMode = streamInImpl(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool, - modeProperties, offset); - return screenModePool.indexOf(screenMode); - } - - - private static ScreenMode streamInImpl(ArrayHashSet resolutionPool, - ArrayHashSet surfaceSizePool, - ArrayHashSet screenSizeMMPool, - ArrayHashSet monitorModePool, - ArrayHashSet screenModePool, - int[] modeProperties, int offset) { - int count = modeProperties[offset]; - if(NUM_SCREEN_MODE_PROPERTIES_ALL != count) { - throw new RuntimeException("NUM_SCREEN_MODE_PROPERTIES should be "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+count+", len "+(modeProperties.length-offset)); - } - if(NUM_SCREEN_MODE_PROPERTIES_ALL > modeProperties.length-offset) { - throw new RuntimeException("properties array too short, should be >= "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset)); - } - offset++; - DimensionImmutable resolution = ScreenModeUtil.streamInResolution(modeProperties, offset); - offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES; - if(null!=resolutionPool) { - resolution = resolutionPool.getOrAdd(resolution); - } - - SurfaceSize surfaceSize = ScreenModeUtil.streamInSurfaceSize(resolution, modeProperties, offset); - offset += ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES; - if(null!=surfaceSizePool) { - surfaceSize = surfaceSizePool.getOrAdd(surfaceSize); - } - - DimensionImmutable screenSizeMM = ScreenModeUtil.streamInResolution(modeProperties, offset); - offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES; - if(null!=screenSizeMMPool) { - screenSizeMM = screenSizeMMPool.getOrAdd(screenSizeMM); - } - - MonitorMode monitorMode = ScreenModeUtil.streamInMonitorMode(surfaceSize, screenSizeMM, modeProperties, offset); - offset += ScreenModeUtil.NUM_MONITOR_MODE_PROPERTIES - ScreenModeUtil.NUM_RESOLUTION_PROPERTIES; - if(null!=monitorModePool) { - monitorMode = monitorModePool.getOrAdd(monitorMode); - } - - ScreenMode screenMode = ScreenModeUtil.streamInScreenMode(monitorMode, modeProperties, offset); - if(null!=screenModePool) { - screenMode = screenModePool.getOrAdd(screenMode); - } - return screenMode; - } - - /** WARNING: must be synchronized with ScreenMode.h, native implementation */ - public static int[] streamOut (ScreenMode screenMode) { - int[] data = new int[NUM_SCREEN_MODE_PROPERTIES_ALL]; - int idx=0; - data[idx++] = NUM_SCREEN_MODE_PROPERTIES_ALL; - data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth(); - data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight(); - data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getBitsPerPixel(); - data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getWidth(); - data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getHeight(); - data[idx++] = screenMode.getMonitorMode().getRefreshRate(); - data[idx++] = screenMode.getRotation(); - if(NUM_SCREEN_MODE_PROPERTIES_ALL != idx) { - throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_SCREEN_MODE_PROPERTIES_ALL); - } - return data; - } - -} diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java new file mode 100644 index 000000000..96daed54a --- /dev/null +++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java @@ -0,0 +1,147 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt; + +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Rectangle; + +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.Screen; + +public class MonitorDeviceImpl extends MonitorDevice { + + public MonitorDeviceImpl(ScreenImpl screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet supportedModes) { + super(screen, nativeId, sizeMM, viewport, currentMode, supportedModes); + } + + @Override + public final MonitorMode queryCurrentMode() { + final ScreenImpl screenImpl = (ScreenImpl)screen; + final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true); + sms.lock(); + try { + final MonitorMode mm0 = screenImpl.queryCurrentMonitorModeIntern(this); + if(null == mm0) { + throw new InternalError("getCurrentMonitorModeIntern() == null"); + } + MonitorMode mmU = supportedModes.get(mm0); // unified instance + if( null == mmU ) { + // add new mode avoiding exception! + mmU = sms.getMonitorModes().getOrAdd(mm0); + mmU = supportedModes.getOrAdd(mmU); + if( Screen.DEBUG ) { + System.err.println("Adding new mode: "+mm0+" -> "+mmU); + } + } + // if mode has changed somehow, update it .. + if( getCurrentMode().hashCode() != mmU.hashCode() ) { + setCurrentModeValue(mmU); + sms.fireScreenModeChanged(this, mmU, true); + } + return mmU; + } finally { + sms.unlock(); + } + } + + @Override + public final boolean setCurrentMode(MonitorMode mode) { + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode.0: "+this+" -> "+mode); + } + final ScreenImpl screenImpl = (ScreenImpl)screen; + final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true); + sms.lock(); + try { + final MonitorMode mmC = queryCurrentMode(); + final MonitorMode mmU = supportedModes.get(mode); // unify via value hash + if( null == mmU ) { + throw new IllegalArgumentException("Given mode not in set of modes. Current mode "+mode+", "+this); + } + if( mmU.equals( mmC ) ) { + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode: 0.0 is-current (skip) "+mmU+" == "+mmC); + } + return true; + } + final long tStart; + if(Screen.DEBUG) { + tStart = System.nanoTime(); + } else { + tStart = 0; + } + + sms.fireScreenModeChangeNotify(this, mmU); + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireScreenModeChangeNotify() "+mmU); + } + + boolean success = screenImpl.setCurrentMonitorModeImpl(this, mmU); + if(success) { + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+mmU+", success(1): "+success); + } + } else { + // 2nd attempt validate! + final MonitorMode queriedCurrent = queryCurrentMode(); // may fireScreenModeChanged(..) if successful and differs! + success = queriedCurrent.hashCode() == mmU.hashCode() ; + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode.2: queried "+queriedCurrent); + System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+mmU+", success(2): "+success); + } + } + if( success ) { + setCurrentModeValue(mmU); + modeChanged = !isOriginalMode(); + } + sms.fireScreenModeChanged(this, mmU, success); + if(Screen.DEBUG) { + System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+this+", success: "+success); + } + return success; + } finally { + sms.unlock(); + } + } + + private final void setCurrentModeValue(MonitorMode currentMode) { + this.currentMode = currentMode; + } + + /* pp */ final void setViewportValue(Rectangle viewport) { + this.viewport = viewport; + } + + /* pp */ ArrayHashSet getSupportedModesImpl() { + return supportedModes; + } + +} \ No newline at end of file diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java new file mode 100644 index 000000000..820807e15 --- /dev/null +++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java @@ -0,0 +1,355 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt; + +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; + +import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.SurfaceSize; + +import jogamp.newt.MonitorDeviceImpl; +import jogamp.newt.ScreenImpl; + +/** + * Encodes and decodes {@link MonitorMode} and {@link MonitorDevice} properties. + */ +public class MonitorModeProps { + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * 2: width, height + */ + public static final int NUM_RESOLUTION_PROPERTIES = 2; + + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * 1: bpp + */ + public static final int NUM_SURFACE_SIZE_PROPERTIES = 1; + + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * 2: refresh-rate (Hz*100), flags + */ + public static final int NUM_SIZEANDRATE_PROPERTIES = 2; + + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * 2: id, rotation + */ + public static final int NUM_MONITOR_MODE_PROPERTIES = 2; + + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * count + all the above + */ + public static final int NUM_MONITOR_MODE_PROPERTIES_ALL = 8; + + public static final int IDX_MONITOR_MODE_BPP = 1 // count + + MonitorModeProps.NUM_RESOLUTION_PROPERTIES + ; + public static final int IDX_MONITOR_MODE_ROT = 1 // count + + MonitorModeProps.NUM_RESOLUTION_PROPERTIES + + MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES + + MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES + + 1 // id of MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES + ; + + /** WARNING: must be synchronized with ScreenMode.h, native implementation + * 10: count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ + */ + public static final int MIN_MONITOR_DEVICE_PROPERTIES = 11; + + public static final int IDX_MONITOR_DEVICE_VIEWPORT = 1 // count + + 1 // native mode + + MonitorModeProps.NUM_RESOLUTION_PROPERTIES // sizeMM + ; + + public static class Cache { + public final ArrayHashSet resolutions = new ArrayHashSet(); + public final ArrayHashSet surfaceSizes = new ArrayHashSet(); + public final ArrayHashSet sizeAndRates = new ArrayHashSet(); + public final ArrayHashSet monitorModes = new ArrayHashSet(); + public final ArrayHashSet monitorDevices = new ArrayHashSet(); + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + private static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) { + Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]); + return resolution; + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + private static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) { + SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]); + return surfaceSize; + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + private static MonitorMode.SizeAndRRate streamInSizeAndRRate(SurfaceSize surfaceSize, int[] sizeAndRRateProperties, int offset) { + final float refreshRate = sizeAndRRateProperties[offset++]/100.0f; + final int flags = sizeAndRRateProperties[offset++]; + return new MonitorMode.SizeAndRRate(surfaceSize, refreshRate, flags); + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + private static MonitorMode streamInMonitorMode0(MonitorMode.SizeAndRRate sizeAndRate, int[] modeProperties, int offset) { + final int id = modeProperties[offset++]; + final int rotation = modeProperties[offset++]; + return new MonitorMode(id, sizeAndRate, rotation); + } + + /** + * WARNING: must be synchronized with ScreenMode.h, native implementation + * + * @param mode_idx if not null and cache is given, returns the index of resulting {@link MonitorMode} within {@link Cache#monitorModes}. + * @param cache optional hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates + * @param modeProperties the input data + * @param offset the offset to the input data + * @return {@link MonitorMode} of the identical (old or new) element in {@link Cache#monitorModes}, + * matching the input modeProperties, or null if input could not be processed. + */ + public static MonitorMode streamInMonitorMode(int[] mode_idx, Cache cache, + int[] modeProperties, int offset) { + final int count = modeProperties[offset]; + if(NUM_MONITOR_MODE_PROPERTIES_ALL != count) { + throw new RuntimeException("property count should be "+NUM_MONITOR_MODE_PROPERTIES_ALL+", but is "+count+", len "+(modeProperties.length-offset)); + } + if(NUM_MONITOR_MODE_PROPERTIES_ALL > modeProperties.length-offset) { + throw new RuntimeException("properties array too short, should be >= "+NUM_MONITOR_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset)); + } + offset++; + DimensionImmutable resolution = MonitorModeProps.streamInResolution(modeProperties, offset); + offset += MonitorModeProps.NUM_RESOLUTION_PROPERTIES; + if(null!=cache) { + resolution = cache.resolutions.getOrAdd(resolution); + } + + SurfaceSize surfaceSize = MonitorModeProps.streamInSurfaceSize(resolution, modeProperties, offset); + offset += MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES; + if(null!=cache) { + surfaceSize = cache.surfaceSizes.getOrAdd(surfaceSize); + } + + MonitorMode.SizeAndRRate sizeAndRate = MonitorModeProps.streamInSizeAndRRate(surfaceSize, modeProperties, offset); + offset += MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES; + if(null!=cache) { + sizeAndRate = cache.sizeAndRates.getOrAdd(sizeAndRate); + } + + MonitorMode monitorMode = MonitorModeProps.streamInMonitorMode0(sizeAndRate, modeProperties, offset); + if(null!=cache) { + monitorMode = cache.monitorModes.getOrAdd(monitorMode); + } + if( null != mode_idx && null!=cache) { + int _modeIdx = cache.monitorModes.indexOf(monitorMode); + if( 0 > _modeIdx ) { + throw new InternalError("Invalid index of current unified mode "+monitorMode); + } + mode_idx[0] = _modeIdx; + } + return monitorMode; + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + public static int[] streamOutMonitorMode (MonitorMode monitorMode) { + int[] data = new int[NUM_MONITOR_MODE_PROPERTIES_ALL]; + int idx=0; + data[idx++] = NUM_MONITOR_MODE_PROPERTIES_ALL; + data[idx++] = monitorMode.getSurfaceSize().getResolution().getWidth(); + data[idx++] = monitorMode.getSurfaceSize().getResolution().getHeight(); + data[idx++] = monitorMode.getSurfaceSize().getBitsPerPixel(); + data[idx++] = (int)(monitorMode.getRefreshRate()*100.0f); // Hz*100 + data[idx++] = monitorMode.getFlags(); + data[idx++] = monitorMode.getId(); + data[idx++] = monitorMode.getRotation(); + if(NUM_MONITOR_MODE_PROPERTIES_ALL != idx) { + throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_MONITOR_MODE_PROPERTIES_ALL); + } + return data; + } + + /** + * WARNING: must be synchronized with ScreenMode.h, native implementation + *

    + * Note: This variant only works for impl. w/ a unique mode key pair modeId, rotation. + *

    + * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. + * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates + * @param modeProperties the input data + * @param offset the offset to the input data + * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices}, + * matching the input modeProperties, or null if input could not be processed. + */ + public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, int[] monitorProperties, int offset) { + // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ + final int count = monitorProperties[offset]; + if(MIN_MONITOR_DEVICE_PROPERTIES > count) { + throw new RuntimeException("property count should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", but is "+count+", len "+(monitorProperties.length-offset)); + } + if(MIN_MONITOR_DEVICE_PROPERTIES > monitorProperties.length-offset) { + throw new RuntimeException("properties array too short (min), should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", is "+(monitorProperties.length-offset)); + } + if(count > monitorProperties.length-offset) { + throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset)); + } + final int limit = offset + count; + offset++; + final List allMonitorModes = cache.monitorModes.getData(); + final int id = monitorProperties[offset++]; + final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES; + final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]); + final MonitorMode currentMode; + { + final int modeId = monitorProperties[offset++]; + final int rotation = monitorProperties[offset++]; + currentMode = getByNativeIdAndRotation(allMonitorModes, modeId, rotation); + } + final ArrayHashSet supportedModes = new ArrayHashSet(); + while( offset < limit ) { + final int modeId = monitorProperties[offset++]; + for (int i=0; i _monitorIdx ) { + throw new InternalError("Invalid index of current unified mode "+monitorDevice); + } + monitor_idx[0] = _monitorIdx; + } + return monitorDevice; + } + private static MonitorMode getByNativeIdAndRotation(List monitorModes, int modeId, int rotation) { + if( null!=monitorModes && monitorModes.size()>0 ) { + for (int i=0; i + * This variant expects count to be {@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}, + * due to lack of supported mode and current mode. + *

    + * + * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. + * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates + * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache. + * @param currentMode pre-fetched current {@link MonitorMode}s from cache. + * @param modeProperties the input data minus supported modes! + * @param offset the offset to the input data + * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices}, + * matching the input modeProperties, or null if input could not be processed. + */ + public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, ArrayHashSet supportedModes, MonitorMode currentMode, int[] monitorProperties, int offset) { + // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ + final int count = monitorProperties[offset]; + if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) { + throw new RuntimeException("property count should be == "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", but is "+count+", len "+(monitorProperties.length-offset)); + } + if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES > monitorProperties.length-offset) { + throw new RuntimeException("properties array too short (min), should be >= "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", is "+(monitorProperties.length-offset)); + } + if(count > monitorProperties.length-offset) { + throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset)); + } + offset++; + final int id = monitorProperties[offset++]; + final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES; + final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]); + MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewport, currentMode, supportedModes); + if(null!=cache) { + monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice); + } + if( null != monitor_idx ) { + int _monitorIdx = cache.monitorDevices.indexOf(monitorDevice); + if( 0 > _monitorIdx ) { + throw new InternalError("Invalid index of current unified mode "+monitorDevice); + } + monitor_idx[0] = _monitorIdx; + } + return monitorDevice; + } + + /** WARNING: must be synchronized with ScreenMode.h, native implementation */ + public static int[] streamOutMonitorDevice (MonitorDevice monitorDevice) { + // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ + int supportedModeCount = monitorDevice.getSupportedModes().size(); + if( 0 == supportedModeCount ) { + throw new RuntimeException("no supported modes: "+monitorDevice); + } + int[] data = new int[MIN_MONITOR_DEVICE_PROPERTIES + supportedModeCount - 1]; + int idx=0; + data[idx++] = data.length; + data[idx++] = monitorDevice.getId(); + data[idx++] = monitorDevice.getSizeMM().getWidth(); + data[idx++] = monitorDevice.getSizeMM().getHeight(); + data[idx++] = monitorDevice.getViewport().getX(); + data[idx++] = monitorDevice.getViewport().getY(); + data[idx++] = monitorDevice.getViewport().getWidth(); + data[idx++] = monitorDevice.getViewport().getHeight(); + data[idx++] = monitorDevice.getCurrentMode().getId(); + data[idx++] = monitorDevice.getCurrentMode().getRotation(); + final List supportedModes = monitorDevice.getSupportedModes(); + for(int i=0; i monitors) { + return false; // nop + } + + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { sizeChanged(false, width, height, false); if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index 1282e5dc5..4d20fdb83 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -43,22 +43,19 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.Point; -import javax.media.nativewindow.util.SurfaceSize; - +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; import com.jogamp.common.util.ArrayHashSet; -import com.jogamp.common.util.IntIntHashMap; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; -import com.jogamp.newt.util.MonitorMode; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; -public abstract class ScreenImpl extends Screen implements ScreenModeListener { +public abstract class ScreenImpl extends Screen implements MonitorModeListener { protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true); public static final int default_sm_bpp = 32; @@ -73,11 +70,11 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { protected int hashCode; protected AbstractGraphicsScreen aScreen; protected int refCount; // number of Screen references by Window - protected Point vOrigin = new Point(0, 0); // virtual top-left origin - protected Dimension vSize = new Dimension(0, 0); // virtual rotated screen size + protected Rectangle vOriginSize = new Rectangle(0, 0, 0, 0); // virtual rotated screen origin and size protected static Dimension usrSize = null; // property values: newt.ws.swidth and newt.ws.sheight protected static volatile boolean usrSizeQueried = false; - private ArrayList referencedScreenModeListener = new ArrayList(); + private ArrayList referencedScreenModeListener = new ArrayList(); + private long tCreated; // creationTime static { @@ -160,10 +157,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { return true; } + @Override public int hashCode() { return hashCode; } + @Override public synchronized final void createNative() throws NativeWindowException { @@ -182,8 +181,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); } - initScreenModeStatus(); - updateVirtualScreenOriginAndSize(); + initScreenMonitorState(); if(DEBUG) { System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), total "+ (System.nanoTime()-tCreated)/1e6 +"ms"); } @@ -191,10 +189,11 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { screensActive++; } } - ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName()); + ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorState(this.getFQName()); sms.addListener(this); } + @Override public synchronized final void destroy() { releaseScreenModeStatus(); @@ -213,6 +212,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { display.removeReference(); } + @Override public synchronized final int addReference() throws NativeWindowException { if(DEBUG) { System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1)); @@ -227,6 +227,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { return ++refCount; } + @Override public synchronized final int removeReference() { if(DEBUG) { System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1)); @@ -240,6 +241,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { return refCount; } + @Override public synchronized final int getReferenceCount() { return refCount; } @@ -259,14 +261,20 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { /** * Stores the virtual origin and virtual rotated screen size. *

    - * This method is called after the ScreenMode has been set, + * This method is called after the ScreenMode has been set or changed, * hence you may utilize it. - *

    - * @param virtualOrigin the store for the virtual origin - * @param virtualSize the store for the virtual rotated size + *

    + *

    + * Default implementation uses the union of all monitor's viewport, + * calculated via {@link #unionOfMonitorViewportSize()}. + *

    + * @param vOriginSize storage for result */ - protected abstract void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize); + protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) { + unionOfMonitorViewportSize(vOriginSize); + } + @Override public final String getFQName() { return fqname; } @@ -275,258 +283,227 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { * Updates the rotated virtual ScreenSize using the native impl. */ protected void updateVirtualScreenOriginAndSize() { - getVirtualScreenOriginAndSize(vOrigin, vSize); - if(DEBUG) { - System.err.println("Detected virtual screen origin "+vOrigin+", size "+vSize); + if(null != usrSize ) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(usrSize.getWidth()); + vOriginSize.setHeight(usrSize.getHeight()); + if(DEBUG) { + System.err.println("User virtual screen viewport "+vOriginSize); + } + } else { + calcVirtualScreenOriginAndSize(vOriginSize); + if(DEBUG) { + System.err.println("Detected virtual screen viewport "+vOriginSize); + } } } + @Override public final Display getDisplay() { return display; } + @Override public final int getIndex() { return screen_idx; } + @Override public final AbstractGraphicsScreen getGraphicsScreen() { return aScreen; } + @Override public synchronized final boolean isNativeValid() { return null != aScreen; } - public int getX() { return vOrigin.getX(); } - public int getY() { return vOrigin.getY(); } - - public final int getWidth() { - return (null != usrSize) ? usrSize.getWidth() : vSize.getWidth(); - } - - public final int getHeight() { - return (null != usrSize) ? usrSize.getHeight() : vSize.getHeight(); - } + @Override + public final int getX() { return vOriginSize.getX(); } + @Override + public final int getY() { return vOriginSize.getY(); } + @Override + public final int getWidth() { return vOriginSize.getWidth(); } + @Override + public final int getHeight() { return vOriginSize.getHeight(); } + @Override + public final RectangleImmutable getViewport() { return vOriginSize; } @Override public String toString() { - return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]"; + return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", vsize "+vOriginSize+", "+aScreen+", "+display+ + ", monitors: "+getMonitorDevices()+"]"; } - public final List getScreenModes() { - ArrayHashSet screenModes = getScreenModesOrig(); - if(null != screenModes && 0 < screenModes.size()) { - return screenModes.toArrayList(); - } - return null; + // + // MonitorDevice and MonitorMode + // + + /** + * To be implemented by the native specification.
    + * Is called within a thread safe environment.
    + * Is called only to collect the {@link MonitorMode}s and {@link MonitorDevice}s, usually at startup setting up modes.
    + *
    + * WARNING: must be synchronized with + *
      + *
    • {@link MonitorModeProps#NUM_SCREEN_MODE_PROPERTIES} and
    • + *
    • {@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}
    • + *
    , i.e. + *
      + *
    • {@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}
    • + *
    • {@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}
    • + *
    • {@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}
    • + *
    + * @param cache memory pool caching the result + */ + protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache); + + protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) { return null; } + + /** + * To be implemented by the native specification.
    + * Is called within a thread safe environment.
    + *

    + * Implementation shall not unify the result w/ monitor's supported modes or a locally + * saved {@link MonitorModeProps.Cache}, since caller will perform such tasks. + *

    + */ + protected abstract MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor); + + /** + * To be implemented by the native specification.
    + * Is called within a thread safe environment.
    + */ + protected abstract boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode); + + @Override + public final List getMonitorModes() { + final ScreenMonitorState sms = getScreenMonitorStatus(false); + return null != sms ? sms.getMonitorModes().getData() : null; + } + + @Override + public final List getMonitorDevices() { + final ScreenMonitorState sms = getScreenMonitorStatus(false); + return null != sms ? sms.getMonitorDevices().getData() : null; } - private final ScreenModeStatus getScreenModeStatus(boolean throwException) { + final ScreenMonitorState getScreenMonitorStatus(boolean throwException) { final String key = this.getFQName(); - final ScreenModeStatus res = ScreenModeStatus.getScreenModeStatus(key); + final ScreenMonitorState res = ScreenMonitorState.getScreenMonitorState(key); if(null == res & throwException) { - throw new InternalError("ScreenModeStatus.getScreenModeStatus("+key+") == null"); + throw new InternalError("ScreenMonitorStatus.getScreenModeStatus("+key+") == null"); } return res; } - public ScreenMode getOriginalScreenMode() { - final ScreenModeStatus sms = getScreenModeStatus(false); - return ( null != sms ) ? sms.getOriginalScreenMode() : null ; - } - - public ScreenMode getCurrentScreenMode() { - ScreenMode smU = null; - final ScreenModeStatus sms = getScreenModeStatus(true); - final ScreenMode sm0 = getCurrentScreenModeIntern(); - if(null == sm0) { - throw new InternalError("getCurrentScreenModeImpl() == null"); + @Override + public void monitorModeChangeNotify(MonitorEvent me) { + if(DEBUG) { + System.err.println("monitorModeChangeNotify: "+me); } - sms.lock(); - try { - smU = sms.getScreenModes().getOrAdd(sm0); // unified instance, maybe new - - // if mode has changed somehow, update it .. - if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) { - sms.fireScreenModeChanged(smU, true); - } - } finally { - sms.unlock(); + for(int i=0; i monitors = getMonitorDevices(); + for(int i=monitors.size()-1; i>=0; i--) { + final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i); + final Rectangle newViewport = getNativeMonitorDeviceViewportImpl(monitor); + if( DEBUG ) { + System.err.println("Screen.updateMonitorViewport["+i+"]: "+monitor.getViewport()+" -> "+newViewport); } - - sms.fireScreenModeChangeNotify(smU); - if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireScreenModeChangeNotify() "+smU); + if( null != newViewport ) { + monitor.setViewportValue(newViewport); } - - success = setCurrentScreenModeImpl(smU); - if(success) { - if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success(1): "+success); - } - } else { - // 2nd attempt validate! - final ScreenMode queriedCurrent = getCurrentScreenMode(); // may fireScreenModeChanged(..) if successful and differs! - final ScreenMode smsCurrent = sms.getCurrentScreenMode(); - success = smsCurrent.hashCode() == smU.hashCode() && queriedCurrent.hashCode() == smU.hashCode() ; - if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode.2: queried "+queriedCurrent); - System.err.println("Screen.setCurrentScreenMode.2: SMS "+smsCurrent); - System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success(2): "+success); - } - } - sms.fireScreenModeChanged(smU, success); - if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+smU+", success: "+success); - } - } finally { - sms.unlock(); - } - return success; + } } - - public void screenModeChangeNotify(ScreenMode sm) { - for(int i=0; i getScreenModesOrig() { - ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName()); - if(null!=sms) { - return sms.getScreenModes(); - } - return null; - } - - /** ScreenModeStatus bridge to native implementation */ - protected final IntIntHashMap getScreenModesIdx2NativeIdx() { - ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName()); - if(null!=sms) { - return sms.getScreenModesIdx2NativeIdx(); - } - return null; - } - - /** - * To be implemented by the native specification.
    - * Is called within a thread safe environment.
    - * Is called only to collect the ScreenModes, usually at startup setting up modes.
    - *
    - * WARNING: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES}, - * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}
    - *
    - * Note: Additional 1st element is native mode id. - */ - protected int[] getScreenModeFirstImpl() { - return null; - } - - /** - * To be implemented by the native specification.
    - * Is called within a thread safe environment.
    - * Is called only to collect the ScreenModes, usually at startup setting up modes.
    - *
    - * WARNING: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES}, - * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}
    - *
    - * Note: Additional 1st element is native mode id. - */ - protected int[] getScreenModeNextImpl() { - return null; + + private final MonitorMode getVirtualMonitorMode(int modeId) { + final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL]; + int i = 0; + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; + props[i++] = getWidth(); // width + props[i++] = getHeight(); // height + props[i++] = default_sm_bpp; + props[i++] = default_sm_rate * 100; + props[i++] = 0; // flags + props[i++] = modeId; + props[i++] = default_sm_rotation; + if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) { + throw new InternalError("XX"); + } + return MonitorModeProps.streamInMonitorMode(null, null, props, 0); } - - /** - * To be implemented by the native specification.
    - * Is called within a thread safe environment.
    - */ - protected ScreenMode getCurrentScreenModeImpl() { - return null; + + private final MonitorDevice getVirtualMonitorDevice(int monitorId, MonitorMode currentMode) { + int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES]; + int i = 0; + props[i++] = MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES; + props[i++] = monitorId; + props[i++] = default_sm_widthmm; + props[i++] = default_sm_heightmm; + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = currentMode.getRotatedWidth(); // rotated viewport width + props[i++] = currentMode.getRotatedHeight(); // rotated viewport height + props[i++] = currentMode.getId(); // current mode id + props[i++] = currentMode.getRotation(); + props[i++] = currentMode.getId(); // supported mode id #1 + if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) { + throw new InternalError("XX"); + } + return MonitorModeProps.streamInMonitorDevice(null, null, this, props, 0); } /** - * Utilizes {@link #getCurrentScreenModeImpl()}, if the latter returns null it uses + * Utilizes {@link #getCurrentMonitorModeImpl()}, if the latter returns null it uses * the current screen size and dummy values. */ - protected ScreenMode getCurrentScreenModeIntern() { - ScreenMode res; + protected final MonitorMode queryCurrentMonitorModeIntern(MonitorDevice monitor) { + MonitorMode res; if(DEBUG_TEST_SCREENMODE_DISABLED) { res = null; } else { - res = getCurrentScreenModeImpl(); + res = queryCurrentMonitorModeImpl(monitor); } if(null == res) { if( 0>=getWidth() || 0>=getHeight() ) { updateVirtualScreenOriginAndSize(); } - int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; - int i = 0; - props[i++] = 0; // set later for verification of iterator - props[i++] = getWidth(); // width - props[i++] = getHeight(); // height - props[i++] = default_sm_bpp; - props[i++] = default_sm_widthmm; - props[i++] = default_sm_heightmm; - props[i++] = default_sm_rate; - props[i++] = default_sm_rotation; - props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count - res = ScreenModeUtil.streamIn(props, 0); + res = getVirtualMonitorMode(monitor.getCurrentMode().getId()); } return res; } - /** - * To be implemented by the native specification.
    - * Is called within a thread safe environment.
    - */ - protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) { - return false; - } - - private ScreenModeStatus initScreenModeStatus() { + private final ScreenMonitorState initScreenMonitorState() { long t0; if(DEBUG) { t0 = System.nanoTime(); @@ -535,138 +512,139 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { t0 = 0; } - ScreenModeStatus sms; - ScreenModeStatus.lockScreenModeStatus(); + boolean vScrnSizeUpdated = false; + ScreenMonitorState sms; + ScreenMonitorState.lockScreenMonitorState(); try { - sms = ScreenModeStatus.getScreenModeStatus(this.getFQName()); - if(null==sms) { - IntIntHashMap screenModesIdx2NativeIdx = new IntIntHashMap(); - final ScreenMode currentSM = getCurrentScreenModeIntern(); - if(null == currentSM) { - throw new InternalError("getCurrentScreenModeImpl() == null"); + sms = ScreenMonitorState.getScreenMonitorState(this.getFQName()); + if(null==sms) { + final MonitorModeProps.Cache cache = new MonitorModeProps.Cache(); + if( 0 >= collectNativeMonitorModes(cache) ) { + updateVirtualScreenOriginAndSize(); + vScrnSizeUpdated = true; + final MonitorMode mode = getVirtualMonitorMode(0); + cache.monitorModes.getOrAdd(mode); + final MonitorDevice monitor = getVirtualMonitorDevice(0, mode); + cache.monitorDevices.getOrAdd(monitor); } - - ArrayHashSet screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx); - screenModes.getOrAdd(currentSM); if(DEBUG) { int i=0; - for(Iterator iter=screenModes.iterator(); iter.hasNext(); i++) { - System.err.println(i+": "+iter.next()); + for(Iterator iMode=cache.monitorModes.iterator(); iMode.hasNext(); i++) { + System.err.println("All["+i+"]: "+iMode.next()); + } + i=0; + for(Iterator iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); i++) { + final MonitorDevice crt = iMonitor.next(); + System.err.println("["+i+"]: "+crt); + int j=0; + for(Iterator iMode=crt.getSupportedModes().iterator(); iMode.hasNext(); j++) { + System.err.println("["+i+"]["+j+"]: "+iMode.next()); + } } } - - sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx); - ScreenMode originalScreenMode0 = screenModes.get(currentSM); // unify via value hash - if(null == originalScreenMode0) { - throw new RuntimeException(currentSM+" could not be hashed from ScreenMode list"); - } - sms.setOriginalScreenMode(originalScreenMode0); - ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms); + sms = new ScreenMonitorState(cache.monitorDevices, cache.monitorModes); + ScreenMonitorState.mapScreenMonitorState(this.getFQName(), sms); } } finally { - ScreenModeStatus.unlockScreenModeStatus(); + ScreenMonitorState.unlockScreenMonitorState(); } if(DEBUG) { System.err.println("Screen.initScreenModeStatus() END dt "+ (System.nanoTime()-t0)/1e6 +"ms"); } + if( !vScrnSizeUpdated ) { + updateVirtualScreenOriginAndSize(); + } + return sms; } - /** ignores bpp < 15 */ - private ArrayHashSet collectNativeScreenModes(IntIntHashMap screenModesIdx2NativeId) { - ArrayHashSet resolutionPool = new ArrayHashSet(); - ArrayHashSet surfaceSizePool = new ArrayHashSet(); - ArrayHashSet screenSizeMMPool = new ArrayHashSet(); - ArrayHashSet monitorModePool = new ArrayHashSet(); - ArrayHashSet screenModePool = new ArrayHashSet(); - - int[] smProps = null; - int num = 0; - final int idxBpp = 1 // native mode - + 1 // count - + ScreenModeUtil.NUM_RESOLUTION_PROPERTIES - + ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES - - 1 ; // index 0 based - do { - if(DEBUG_TEST_SCREENMODE_DISABLED) { - smProps = null; - } else if(0 == num) { - smProps = getScreenModeFirstImpl(); - } else { - smProps = getScreenModeNextImpl(); - } - if(null != smProps && 0 < smProps.length && smProps[idxBpp] >= 15) { - int nativeId = smProps[0]; - int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool, - monitorModePool, screenModePool, smProps, 1); - if(DEBUG) { - System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": idx: "+nativeId+" native -> "+screenModeIdx+" newt"); + /** + * Returns the number of successful collected {@link MonitorDevice}s. + *

    + * Collects {@link MonitorDevice}s and {@link MonitorMode}s within the given cache. + *

    + */ + private final int collectNativeMonitorModes(MonitorModeProps.Cache cache) { + if(!DEBUG_TEST_SCREENMODE_DISABLED) { + collectNativeMonitorModesAndDevicesImpl(cache); + } + // filter out insufficient modes + for(int i=cache.monitorModes.size()-1; i>=0; i--) { + final MonitorMode mode = cache.monitorModes.get(i); + if( 16 > mode.getSurfaceSize().getBitsPerPixel() ) { + boolean keep = false; + for(int j=cache.monitorDevices.size()-1; !keep && j>=0; j--) { + final MonitorDevice monitor = cache.monitorDevices.get(j); + keep = monitor.getCurrentMode().equals(mode); } - - if(screenModeIdx >= 0) { - screenModesIdx2NativeId.put(screenModeIdx, nativeId); + if(!keep) { + cache.monitorModes.remove(i); + for(int j=cache.monitorDevices.size()-1; j>=0; j--) { + final MonitorDeviceImpl monitor = (MonitorDeviceImpl) cache.monitorDevices.get(j); + monitor.getSupportedModesImpl().remove(mode); + } } - } else if(DEBUG) { - System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": smProps: "+(null!=smProps)+ - ", len: "+(null != smProps ? smProps.length : 0)+ - ", bpp: "+(null != smProps && 0 < smProps.length ? smProps[idxBpp] : 0)+ - " - DROPPING"); } - num++; - } while ( null != smProps && 0 < smProps.length ); - - if(DEBUG) { - System.err.println("ScreenImpl.collectNativeScreenModes: ScreenMode number : "+screenModePool.size()); - System.err.println("ScreenImpl.collectNativeScreenModes: MonitorMode number : "+monitorModePool.size()); - System.err.println("ScreenImpl.collectNativeScreenModes: ScreenSizeMM number: "+screenSizeMMPool.size()); - System.err.println("ScreenImpl.collectNativeScreenModes: SurfaceSize number : "+surfaceSizePool.size()); - System.err.println("ScreenImpl.collectNativeScreenModes: Resolution number : "+resolutionPool.size()); } - - return screenModePool; + if( DEBUG ) { + System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorDevice number : "+cache.monitorDevices.size()); + System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorMode number : "+cache.monitorModes.size()); + System.err.println("ScreenImpl.collectNativeMonitorModes: SizeAndRate number : "+cache.sizeAndRates.size()); + System.err.println("ScreenImpl.collectNativeMonitorModes: SurfaceSize number : "+cache.surfaceSizes.size()); + System.err.println("ScreenImpl.collectNativeMonitorModes: Resolution number : "+cache.resolutions.size()); + } + return cache.monitorDevices.size(); } private void releaseScreenModeStatus() { - ScreenModeStatus sms; - ScreenModeStatus.lockScreenModeStatus(); + ScreenMonitorState sms; + ScreenMonitorState.lockScreenMonitorState(); try { - sms = ScreenModeStatus.getScreenModeStatus(getFQName()); + sms = ScreenMonitorState.getScreenMonitorState(getFQName()); if(null != sms) { sms.lock(); try { if(0 == sms.removeListener(this)) { - if(sms.isOriginalModeChangedByOwner()) { - System.err.println("Screen.destroy(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode()); - try { - setCurrentScreenMode(sms.getOriginalScreenMode()); - } catch (Throwable t) { - // be verbose but continue - t.printStackTrace(); + final ArrayList monitorDevices = sms.getMonitorDevices().getData(); + for(int i=0; i "+sms.getOriginalScreenMode()); - setCurrentScreenModeImpl(sms.getOriginalScreenMode()); - } catch (Throwable t) { - // be quiet .. shutdown + final ArrayList monitorDevices = sms.getMonitorDevices().getData(); + for(int i=0; i screenModes; - private IntIntHashMap screenModesIdx2NativeIdx; - private ScreenMode currentScreenMode; - private ScreenMode originalScreenMode; - private boolean screenModeChangedByOwner; - private ArrayList listener = new ArrayList(); - - private static HashMap screenFQN2ScreenModeStatus = new HashMap(); - private static RecursiveLock screen2ScreenModeStatusLock = LockFactory.createRecursiveLock(); - - protected static void mapScreenModeStatus(String screenFQN, ScreenModeStatus sms) { - screen2ScreenModeStatusLock.lock(); - try { - ScreenModeStatus _sms = screenFQN2ScreenModeStatus.get(screenFQN); - if( null != _sms ) { - throw new RuntimeException("ScreenModeStatus "+_sms+" already mapped to "+screenFQN); - } - screenFQN2ScreenModeStatus.put(screenFQN, sms); - if(DEBUG) { - System.err.println("ScreenModeStatus.map "+screenFQN+" -> "+sms); - } - } finally { - screen2ScreenModeStatusLock.unlock(); - } - } - - /** - * @param screen the prev user - * @return true if mapping is empty, ie no more usage of the mapped ScreenModeStatus - */ - protected static void unmapScreenModeStatus(String screenFQN) { - screen2ScreenModeStatusLock.lock(); - try { - unmapScreenModeStatusUnlocked(screenFQN); - } finally { - screen2ScreenModeStatusLock.unlock(); - } - } - protected static void unmapScreenModeStatusUnlocked(String screenFQN) { - ScreenModeStatus sms = screenFQN2ScreenModeStatus.remove(screenFQN); - if(DEBUG) { - System.err.println("ScreenModeStatus.unmap "+screenFQN+" -> "+sms); - } - } - - protected static ScreenModeStatus getScreenModeStatus(String screenFQN) { - screen2ScreenModeStatusLock.lock(); - try { - return getScreenModeStatusUnlocked(screenFQN); - } finally { - screen2ScreenModeStatusLock.unlock(); - } - } - protected static ScreenModeStatus getScreenModeStatusUnlocked(String screenFQN) { - return screenFQN2ScreenModeStatus.get(screenFQN); - } - - protected static void lockScreenModeStatus() { - screen2ScreenModeStatusLock.lock(); - } - - protected static void unlockScreenModeStatus() { - screen2ScreenModeStatusLock.unlock(); - } - - public ScreenModeStatus(ArrayHashSet screenModes, - IntIntHashMap screenModesIdx2NativeIdx) { - this.screenModes = screenModes; - this.screenModesIdx2NativeIdx = screenModesIdx2NativeIdx; - this.screenModeChangedByOwner = false; - } - - protected final void setOriginalScreenMode(ScreenMode originalScreenMode) { - this.originalScreenMode = originalScreenMode; - this.currentScreenMode = originalScreenMode; - } - - public final ScreenMode getOriginalScreenMode() { - return originalScreenMode; - } - - public final ScreenMode getCurrentScreenMode() { - lock(); - try { - return currentScreenMode; - } finally { - unlock(); - } - } - - /** - * We cannot guarantee that we won't interfere w/ another running - * application's screen mode change. - *

    - * At least we only return true if the owner, ie. the Screen, - * has changed the screen mode and if the original screen mode - * is not current the current one. - *

    - * @return - */ - public final boolean isOriginalModeChangedByOwner() { - lock(); - try { - return screenModeChangedByOwner && !isCurrentModeOriginalMode(); - } finally { - unlock(); - } - } - - protected final boolean isCurrentModeOriginalMode() { - if(null != currentScreenMode && null != originalScreenMode) { - return currentScreenMode.hashCode() == originalScreenMode.hashCode(); - } - return true; - } - - protected final ArrayHashSet getScreenModes() { - return screenModes; - } - - protected final IntIntHashMap getScreenModesIdx2NativeIdx() { - return screenModesIdx2NativeIdx; - } - - protected final int addListener(ScreenModeListener l) { - lock(); - try { - listener.add(l); - if(DEBUG) { - System.err.println("ScreenModeStatus.addListener (size: "+listener.size()+"): "+l); - } - return listener.size(); - } finally { - unlock(); - } - } - - protected final int removeListener(ScreenModeListener l) { - lock(); - try { - if(!listener.remove(l)) { - throw new RuntimeException("ScreenModeListener "+l+" not contained"); - } - if(DEBUG) { - System.err.println("ScreenModeStatus.removeListener (size: "+listener.size()+"): "+l); - } - return listener.size(); - } finally { - unlock(); - } - } - - protected final void fireScreenModeChangeNotify(ScreenMode desiredScreenMode) { - lock(); - try { - for(int i=0; i allMonitors; + private final ArrayHashSet allMonitorModes; + private ArrayList listener = new ArrayList(); + + private static HashMap screenFQN2ScreenMonitorState = new HashMap(); + private static RecursiveLock screen2ScreenMonitorState = LockFactory.createRecursiveLock(); + + protected static void mapScreenMonitorState(String screenFQN, ScreenMonitorState sms) { + screen2ScreenMonitorState.lock(); + try { + ScreenMonitorState _sms = screenFQN2ScreenMonitorState.get(screenFQN); + if( null != _sms ) { + throw new RuntimeException("ScreenMonitorState "+_sms+" already mapped to "+screenFQN); + } + screenFQN2ScreenMonitorState.put(screenFQN, sms); + if(DEBUG) { + System.err.println("ScreenMonitorState.map "+screenFQN+" -> "+sms); + } + } finally { + screen2ScreenMonitorState.unlock(); + } + } + + /** + * @param screen the prev user + * @return true if mapping is empty, ie no more usage of the mapped ScreenMonitorState + */ + protected static void unmapScreenMonitorState(String screenFQN) { + screen2ScreenMonitorState.lock(); + try { + unmapScreenMonitorStateUnlocked(screenFQN); + } finally { + screen2ScreenMonitorState.unlock(); + } + } + protected static void unmapScreenMonitorStateUnlocked(String screenFQN) { + ScreenMonitorState sms = screenFQN2ScreenMonitorState.remove(screenFQN); + if(DEBUG) { + System.err.println("ScreenMonitorState.unmap "+screenFQN+" -> "+sms); + } + } + + protected static ScreenMonitorState getScreenMonitorState(String screenFQN) { + screen2ScreenMonitorState.lock(); + try { + return getScreenMonitorStateUnlocked(screenFQN); + } finally { + screen2ScreenMonitorState.unlock(); + } + } + protected static ScreenMonitorState getScreenMonitorStateUnlocked(String screenFQN) { + return screenFQN2ScreenMonitorState.get(screenFQN); + } + + protected static void lockScreenMonitorState() { + screen2ScreenMonitorState.lock(); + } + + protected static void unlockScreenMonitorState() { + screen2ScreenMonitorState.unlock(); + } + + public ScreenMonitorState(ArrayHashSet allMonitors, + ArrayHashSet allMonitorModes) { + this.allMonitors = allMonitors; + this.allMonitorModes = allMonitorModes; + } + + protected ArrayHashSet getMonitorDevices() { + return allMonitors; + } + + protected ArrayHashSet getMonitorModes() { + return allMonitorModes; + } + + protected final int addListener(MonitorModeListener l) { + lock(); + try { + listener.add(l); + if(DEBUG) { + System.err.println("ScreenMonitorState.addListener (size: "+listener.size()+"): "+l); + } + return listener.size(); + } finally { + unlock(); + } + } + + protected final int removeListener(MonitorModeListener l) { + lock(); + try { + if(!listener.remove(l)) { + throw new RuntimeException("ScreenModeListener "+l+" not contained"); + } + if(DEBUG) { + System.err.println("ScreenMonitorState.removeListener (size: "+listener.size()+"): "+l); + } + return listener.size(); + } finally { + unlock(); + } + } + + protected final MonitorDevice getMonitor(MonitorDevice monitor) { + return allMonitors.get(monitor); + } + + protected final void validateMonitor(MonitorDevice monitor) { + final MonitorDevice md = allMonitors.get(monitor); + if( null == md ) { + throw new InternalError("Monitor unknown: "+monitor); + } + } + + protected final void fireScreenModeChangeNotify(MonitorDevice monitor, MonitorMode desiredMode) { + lock(); + try { + validateMonitor(monitor); + final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGE_NOTIFY, monitor, System.currentTimeMillis(), desiredMode); + for(int i=0; i default - private boolean fullscreen = false, brokenFocusChange = false; + private boolean fullscreen = false, brokenFocusChange = false; + private List fullscreenMonitors = null; + private boolean fullscreenUseMainMonitor = true; private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user) private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets @@ -294,19 +298,40 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer screenReferenceAdded = true; } if(canCreateNativeImpl()) { + final int wX, wY; + final boolean usePosition; + if( autoPosition ) { + wX = 0; + wY = 0; + usePosition = false; + } else { + wX = getX(); + wY = getY(); + usePosition = true; + } + final long t0 = System.currentTimeMillis(); createNativeImpl(); - screen.addScreenModeListener(screenModeListenerImpl); + screen.addMonitorModeListener(screenModeListenerImpl); setTitleImpl(title); setPointerVisibleImpl(pointerVisible); confinePointerImpl(pointerConfined); setKeyboardVisible(keyboardVisible); - if(waitForVisible(true, false)) { + final long remainingV = waitForVisible(true, false); + if( 0 <= remainingV ) { if(isFullscreen()) { synchronized(fullScreenAction) { fullscreen = false; // trigger a state change - fullScreenAction.init(true); + fullScreenAction.init(true, fullscreenUseMainMonitor, fullscreenMonitors); + fullscreenMonitors = null; // release references ASAP + fullscreenUseMainMonitor = true; fullScreenAction.run(); } + } else { + // Wait until position is reached within tolerances, either auto-position or custom position. + waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW); + } + if (DEBUG_IMPLEMENTATION) { + System.err.println("Window.createNative(): elapsed "+(System.currentTimeMillis()-t0)+" ms"); } postParentlockFocus = true; } @@ -463,8 +488,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public static final int FLAG_HAS_PARENT = 1 << 8; public static final int FLAG_IS_UNDECORATED = 1 << 9; public static final int FLAG_IS_FULLSCREEN = 1 << 10; - public static final int FLAG_IS_ALWAYSONTOP = 1 << 11; - public static final int FLAG_IS_VISIBLE = 1 << 12; + public static final int FLAG_IS_FULLSCREEN_SPAN = 1 << 11; + public static final int FLAG_IS_ALWAYSONTOP = 1 << 12; + public static final int FLAG_IS_VISIBLE = 1 << 13; /** * The native implementation should invoke the referenced java state callbacks @@ -509,6 +535,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } sb.append("FS_"); sb.append(0 != ( FLAG_IS_FULLSCREEN & flags)); + sb.append("_span_"); + sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags)); sb.append(", "); if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) { @@ -718,6 +746,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return screen; } + @Override + public final MonitorDevice getMainMonitor() { + return screen.getMainMonitor(new Rectangle(getX(), getY(), getWidth(), getHeight())); + } + protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) { reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible)); } @@ -904,7 +937,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if( isNativeValid() ) { - screen.removeScreenModeListener(screenModeListenerImpl); + screen.removeMonitorModeListener(screenModeListenerImpl); closeNativeImpl(); final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice(); if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device @@ -929,6 +962,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer setWindowHandle(0); visible = false; fullscreen = false; + fullscreenMonitors = null; + fullscreenUseMainMonitor = true; hasFocus = false; parentWindowHandle = 0; @@ -1212,7 +1247,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer display.dispatchMessagesNative(); // status up2date if(wasVisible) { setVisibleImpl(true, x, y, width, height); - ok = WindowImpl.this.waitForVisible(true, false); + ok = 0 <= WindowImpl.this.waitForVisible(true, false); if(ok) { ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW); } @@ -1735,6 +1770,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(isNativeValid()) { // this.x/this.y will be set by sizeChanged, triggered by windowing event system reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible())); + + // Wait until custom position is reached within tolerances + waitForPosition(true, x, y, Window.TIMEOUT_NATIVEWINDOW); } else { definePosition(x, y); // set pos for createNative(..) } @@ -1758,13 +1796,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private class FullScreenAction implements Runnable { boolean fullscreen; + List monitors; + boolean useMainMonitor; - private boolean init(boolean fullscreen) { + private boolean init(boolean fullscreen, boolean useMainMonitor, List monitors) { if(isNativeValid()) { this.fullscreen = fullscreen; - return isFullscreen() != fullscreen; + if( isFullscreen() != fullscreen ) { + this.monitors = monitors; + this.useMainMonitor = useMainMonitor; + return true; + } else { + this.monitors = null; + this.useMainMonitor = true; + return false; + } } else { WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..) + WindowImpl.this.fullscreenMonitors = monitors; + WindowImpl.this.fullscreenUseMainMonitor = useMainMonitor; return false; } } @@ -1777,19 +1827,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // set current state WindowImpl.this.fullscreen = fullscreen; - final ScreenMode sm = screen.getCurrentScreenMode(); int x,y,w,h; + final RectangleImmutable viewport; + final int fs_span_flag; if(fullscreen) { + if( null == monitors ) { + if( useMainMonitor ) { + monitors = new ArrayList(); + monitors.add( getMainMonitor() ); + } else { + monitors = getScreen().getMonitorDevices(); + } + } + fs_span_flag = monitors.size() > 1 ? FLAG_IS_FULLSCREEN_SPAN : 0 ; + viewport = MonitorDevice.unionOfViewports(new Rectangle(), monitors); nfs_x = getX(); nfs_y = getY(); nfs_width = getWidth(); nfs_height = getHeight(); - x = screen.getX(); - y = screen.getY(); - w = sm.getRotatedWidth(); - h = sm.getRotatedHeight(); + x = viewport.getX(); + y = viewport.getY(); + w = viewport.getWidth(); + h = viewport.getHeight(); } else { + fs_span_flag = 0; + viewport = null; x = nfs_x; y = nfs_y; w = nfs_width; @@ -1809,9 +1872,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } + monitors = null; // clear references ASAP + useMainMonitor = true; if(DEBUG_IMPLEMENTATION) { System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+ - ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", SM "+sm.getRotatedWidth()+"x"+sm.getRotatedHeight()); + ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", monitorsViewport "+viewport); } DisplayImpl display = (DisplayImpl) screen.getDisplay(); @@ -1831,7 +1896,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer try { reconfigureWindowImpl(x, y, w, h, getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) | - FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); + fs_span_flag | FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); } finally { if(null!=parentWindowLocked) { parentWindowLocked.unlockSurface(); @@ -1860,8 +1925,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public boolean setFullscreen(boolean fullscreen) { + return setFullscreenImpl(fullscreen, true, null); + } + + @Override + public boolean setFullscreen(List monitors) { + return setFullscreenImpl(true, false, monitors); + } + + private boolean setFullscreenImpl(boolean fullscreen, boolean useMainMonitor, List monitors) { synchronized(fullScreenAction) { - if( fullScreenAction.init(fullscreen) ) { + if( fullScreenAction.init(fullscreen, useMainMonitor, monitors) ) { if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) { // enable fullscreen on offscreen instance if(null != parentWindow) { @@ -1887,13 +1961,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return this.fullscreen; } } - - private class ScreenModeListenerImpl implements ScreenModeListener { + + private class ScreenModeListenerImpl implements MonitorModeListener { boolean animatorPaused = false; - public void screenModeChangeNotify(ScreenMode sm) { + public void monitorModeChangeNotify(MonitorEvent me) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.screenModeChangeNotify: "+sm); + System.err.println("Window.screenModeChangeNotify: "+me); } if(null!=lifecycleHook) { @@ -1901,9 +1975,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void screenModeChanged(ScreenMode sm, boolean success) { + public void monitorModeChanged(MonitorEvent me, boolean success) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.screenModeChanged: "+sm+", success: "+success); + System.err.println("Window.screenModeChanged: "+me+", success: "+success); } if(success) { @@ -1911,10 +1985,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Didn't pass above notify method. probably detected screen change after it happened. animatorPaused = lifecycleHook.pauseRenderingAction(); } - DimensionImmutable screenSize = sm.getMonitorMode().getSurfaceSize().getResolution(); - if ( getHeight() > screenSize.getHeight() || - getWidth() > screenSize.getWidth() ) { - setSize(screenSize.getWidth(), screenSize.getHeight()); + if( !fullscreen ) { + // FIXME: Need to take all covered monitors into account + final MonitorDevice mainMonitor = getMainMonitor(); + final MonitorDevice eventMonitor = me.getMonitor(); + if( mainMonitor == eventMonitor ) { + final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight()); + final RectangleImmutable viewport = mainMonitor.getViewport(); + final RectangleImmutable isect = viewport.intersection(rect); + if ( getHeight() > isect.getHeight() || + getWidth() > isect.getWidth() ) { + setSize(isect.getWidth(), isect.getHeight()); + } + } } } @@ -2563,14 +2646,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - private boolean waitForVisible(boolean visible, boolean failFast) { + /** Returns -1 if failed, otherwise remaining time until {@link #TIMEOUT_NATIVEWINDOW}, maybe zero. */ + private long waitForVisible(boolean visible, boolean failFast) { return waitForVisible(visible, failFast, TIMEOUT_NATIVEWINDOW); } - private boolean waitForVisible(boolean visible, boolean failFast, long timeOut) { + /** Returns -1 if failed, otherwise remaining time until timeOut, maybe zero. */ + private long waitForVisible(boolean visible, boolean failFast, long timeOut) { final DisplayImpl display = (DisplayImpl) screen.getDisplay(); display.dispatchMessagesNative(); // status up2date - for(long sleep = timeOut; 0 + * Since WM may not obey our positional request exactly, we allow a tolerance of 2 times insets[left/top], or 64 pixels, whatever is greater. + *

    + */ + private boolean waitForPosition(boolean useCustomPosition, int x, int y, long timeOut) { + final DisplayImpl display = (DisplayImpl) screen.getDisplay(); + final int maxDX, maxDY; + { + final InsetsImmutable insets = getInsets(); + maxDX = Math.max(64, insets.getLeftWidth() * 2); + maxDY = Math.max(64, insets.getTopHeight() * 2); + } + long remaining = timeOut; + boolean ok; + do { + if( useCustomPosition ) { + ok = Math.abs(x - getX()) <= maxDX && Math.abs(y - getY()) <= maxDY ; + } else { + ok = !autoPosition; + } + if( !ok ) { + try { Thread.sleep(10); } catch (InterruptedException ie) {} + display.dispatchMessagesNative(); // status up2date + remaining-=10; + } + } while ( 0getX() || 0>getY()) { diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java index 6b1283a00..8e584fc58 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java @@ -35,12 +35,15 @@ package jogamp.newt.driver.awt; import java.awt.DisplayMode; +import jogamp.newt.MonitorModeProps.Cache; import jogamp.newt.ScreenImpl; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.Point; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public class ScreenDriver extends ScreenImpl { public ScreenDriver() { @@ -68,14 +71,19 @@ public class ScreenDriver extends ScreenImpl { return idx; // pass through ... } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); - if(null != mode) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(mode.getWidth()); - virtualSize.setHeight(mode.getHeight()); - } + @Override + protected void collectNativeMonitorModesAndDevicesImpl(Cache cache) { + final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); + } + + @Override + protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) { + return null; + } + + @Override + protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) { + return false; } } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java index deb2a534b..afaedffe3 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java @@ -35,8 +35,13 @@ package jogamp.newt.driver.bcm.egl; import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.Rectangle; + +import jogamp.newt.MonitorModeProps; +import jogamp.newt.ScreenImpl; + +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public class ScreenDriver extends jogamp.newt.ScreenImpl { @@ -58,11 +63,48 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl { return 0; // only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(fixedWidth); // FIXME - virtualSize.setHeight(fixedHeight); // FIXME + @Override + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; + int i = 0; + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; + props[i++] = fixedWidth; // FIXME + props[i++] = fixedHeight; // FIXME + props[i++] = ScreenImpl.default_sm_bpp; // FIXME + props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME + props[i++] = 0; // flags + props[i++] = 0; // mode_idx + props[i++] = 0; // rotation + final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + + props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES]; + i = 0; + props[i++] = props.length; + props[i++] = 0; // crt_idx + props[i++] = ScreenImpl.default_sm_widthmm; // FIXME + props[i++] = ScreenImpl.default_sm_heightmm; // FIXME + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = fixedWidth; // FIXME rotated viewport width + props[i++] = fixedHeight; // FIXME rotated viewport height + MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + } + + @Override + protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) { + return monitor.getSupportedModes().get(0); + } + + @Override + protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) { + return false; + } + + protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(fixedWidth); // FIXME + vOriginSize.setHeight(fixedHeight); // FIXME } //---------------------------------------------------------------------- diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java index 787d1a1b4..f7973def8 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java @@ -29,9 +29,12 @@ package jogamp.newt.driver.bcm.vc.iv; import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.Rectangle; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; + +import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; public class ScreenDriver extends ScreenImpl { @@ -53,13 +56,52 @@ public class ScreenDriver extends ScreenImpl { return 0; // only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); + @Override + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; + int i = 0; + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; + props[i++] = cachedWidth; // width + props[i++] = cachedHeight; // height + props[i++] = ScreenImpl.default_sm_bpp; // FIXME + props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME + props[i++] = 0; // flags + props[i++] = 0; // mode_idx + props[i++] = 0; // rotation + final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + + props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES]; + i = 0; + props[i++] = props.length; + props[i++] = 0; // crt_idx + props[i++] = ScreenImpl.default_sm_widthmm; // FIXME + props[i++] = ScreenImpl.default_sm_heightmm; // FIXME + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = cachedWidth; // rotated viewport width + props[i++] = cachedWidth; // rotated viewport height + MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + } + + @Override + protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) { + return monitor.getSupportedModes().get(0); + } + + @Override + protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) { + return false; + } + + @Override + protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(cachedWidth); + vOriginSize.setHeight(cachedHeight); } + /** Called from {@link #initNative()}. */ protected void setScreenSize(int width, int height) { cachedWidth = width; cachedHeight = height; diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java index 8eed14dde..4c47eb0d8 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java @@ -36,8 +36,13 @@ package jogamp.newt.driver.intel.gdl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.Rectangle; + +import jogamp.newt.MonitorModeProps; +import jogamp.newt.ScreenImpl; + +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public class ScreenDriver extends jogamp.newt.ScreenImpl { @@ -60,11 +65,48 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl { return 0; // only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); + @Override + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; + int i = 0; + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; + props[i++] = cachedWidth; // width + props[i++] = cachedHeight; // height + props[i++] = ScreenImpl.default_sm_bpp; // FIXME + props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME + props[i++] = 0; // flags + props[i++] = 0; // mode_idx + props[i++] = 0; // rotation + final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + + props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES]; + i = 0; + props[i++] = props.length; + props[i++] = 0; // crt_idx + props[i++] = ScreenImpl.default_sm_widthmm; // FIXME + props[i++] = ScreenImpl.default_sm_heightmm; // FIXME + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = cachedWidth; // rotated viewport width + props[i++] = cachedWidth; // rotated viewport height + MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + } + + @Override + protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) { + return monitor.getSupportedModes().get(0); + } + + @Override + protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) { + return false; + } + + protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(cachedWidth); + vOriginSize.setHeight(cachedHeight); } //---------------------------------------------------------------------- diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java index 656bcf5c9..dc87c3c08 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java @@ -35,9 +35,12 @@ package jogamp.newt.driver.kd; import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.Rectangle; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; + +import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; public class ScreenDriver extends ScreenImpl { @@ -58,11 +61,48 @@ public class ScreenDriver extends ScreenImpl { return 0; // only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(cachedWidth); - virtualSize.setHeight(cachedHeight); + @Override + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; + int i = 0; + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; + props[i++] = cachedWidth; // width + props[i++] = cachedHeight; // height + props[i++] = ScreenImpl.default_sm_bpp; // FIXME + props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME + props[i++] = 0; // flags + props[i++] = 0; // mode_idx + props[i++] = 0; // rotation + final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + + props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES]; + i = 0; + props[i++] = props.length; + props[i++] = 0; // crt_idx + props[i++] = ScreenImpl.default_sm_widthmm; // FIXME + props[i++] = ScreenImpl.default_sm_heightmm; // FIXME + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = cachedWidth; // rotated viewport width + props[i++] = cachedWidth; // rotated viewport height + MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + } + + @Override + protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) { + return monitor.getSupportedModes().get(0); + } + + @Override + protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) { + return false; + } + + protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) { + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(cachedWidth); + vOriginSize.setHeight(cachedHeight); } protected void sizeChanged(int w, int h) { diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java index 24e60ba0a..a3bb26731 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java @@ -34,28 +34,19 @@ package jogamp.newt.driver.macosx; -import java.util.List; - import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.Point; +import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; -import com.jogamp.common.util.IntObjectHashMap; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public class ScreenDriver extends ScreenImpl { - // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) - private static IntObjectHashMap/**/ scrnIdx2Dimension; - static { DisplayDriver.initSingleton(); - scrnIdx2Dimension = new IntObjectHashMap(); - scrnIdx2Dimension.setKeyNotFoundValue(null); } public ScreenDriver() { @@ -67,77 +58,67 @@ public class ScreenDriver extends ScreenImpl { protected void closeNativeImpl() { } - private static native int getWidthImpl0(int scrn_idx); - private static native int getHeightImpl0(int scrn_idx); - - private int[] getScreenModeIdx(int idx) { - // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) - DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx); - if(null == dim) { - int[] res = getScreenSizeMM0(screen_idx); - if(null == res || 0 == res.length) { - return null; - } - dim = new Dimension(res[0], res[1]); - scrnIdx2Dimension.put(screen_idx, dim); - } - - int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight()); - if (null == modeProps || 0 == modeProps.length) { - return null; + private MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, int crt_idx, int mode_idx) { + final int[] modeProps = getMonitorMode0(crt_idx, mode_idx); + final MonitorMode res; + if (null == modeProps || 0 >= modeProps.length) { + res = null; + } else { + res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0); } - if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { - throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); - } - return modeProps; + return res; } - - private int nativeModeIdx; - protected int[] getScreenModeFirstImpl() { - nativeModeIdx = 0; - return getScreenModeNextImpl(); - } - - protected int[] getScreenModeNextImpl() { - int[] modeProps = getScreenModeIdx(nativeModeIdx); - if (null != modeProps && 0 < modeProps.length) { - nativeModeIdx++; - return modeProps; - } - return null; + @Override + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int crtIdx = 0; + int modeIdx = 0; + ArrayHashSet supportedModes = new ArrayHashSet(); + do { + final MonitorMode mode = getMonitorModeImpl(cache, crtIdx, modeIdx); + if( null != mode ) { + supportedModes.getOrAdd(mode); + // next mode on same monitor + modeIdx++; + } else if( 0 < modeIdx ) { + // end of monitor modes - got at least one mode + final MonitorMode currentMode = getMonitorModeImpl(cache, crtIdx, -1); + if ( null == currentMode ) { + throw new InternalError("Could not gather current mode of device "+crtIdx+", but gathered "+modeIdx+" modes"); + } + final int[] monitorProps = getMonitorProps0(crtIdx); + if ( null == monitorProps ) { + throw new InternalError("Could not gather device "+crtIdx+", but gathered "+modeIdx+" modes"); + } + // merge monitor-props + supported modes + MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0); + + // next monitor, 1st mode + supportedModes= new ArrayHashSet(); + crtIdx++; + modeIdx=0; + } else { + // end of monitor + break; + } + } while ( true ); } - protected ScreenMode getCurrentScreenModeImpl() { - int[] modeProps = getScreenModeIdx(-1); - if (null != modeProps && 0 < modeProps.length) { - return ScreenModeUtil.streamIn(modeProps, 0); - } - return null; + @Override + protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) { + return getMonitorModeImpl(null, monitor.getId(), -1); } - protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { - final List screenModes = this.getScreenModesOrig(); - final int screenModeIdx = screenModes.indexOf(screenMode); - if(0>screenModeIdx) { - throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); - } - final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); - return setScreenMode0(screen_idx, nativeModeIdx); + @Override + protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) { + return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation()); } protected int validateScreenIndex(int idx) { - return idx; + return 0; // big-desktop w/ multiple monitor attached, only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(getWidthImpl0(screen_idx)); - virtualSize.setHeight(getHeightImpl0(screen_idx)); - } - - private native int[] getScreenSizeMM0(int screen_idx); - private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM); - private native boolean setScreenMode0(int screen_index, int mode_idx); + private native int[] getMonitorProps0(int crt_idx); + private native int[] getMonitorMode0(int crt_index, int mode_idx); + private native boolean setMonitorMode0(int crt_index, int nativeId, int rot); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index bb72350e3..6370782df 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -478,7 +478,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( 0 != surfaceHandle ) { throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView"); } - surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen, getScreen().getIndex()); + surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen); if( 0 == surfaceHandle ) { throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); } @@ -487,7 +487,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen, ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask : NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask, - NSBackingStoreBuffered, getScreen().getIndex(), surfaceHandle); + NSBackingStoreBuffered, surfaceHandle); if ( newWin == 0 ) { throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); } @@ -497,9 +497,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // Non blocking initialization on main-thread! OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { - initWindow0( parentWin, newWin, - pS.getX(), pS.getY(), width, height, - isOpaque, fullscreen, visible && !offscreenInstance, getScreen().getIndex(), surfaceHandle); + initWindow0( parentWin, newWin, pS.getX(), pS.getY(), width, height, + isOpaque, fullscreen, visible && !offscreenInstance, surfaceHandle); if( offscreenInstance ) { orderOut0(0!=parentWin ? parentWin : newWin); } else { @@ -514,11 +513,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } protected static native boolean initIDs0(); - private native long createView0(int x, int y, int w, int h, boolean fullscreen, int screen_idx); - private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, int screen_idx, long view); + private native long createView0(int x, int y, int w, int h, boolean fullscreen); + private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view); /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, boolean visible, int screen_idx, long view); + boolean opaque, boolean fullscreen, boolean visible, long view); private native boolean lockSurface0(long window, long view); private native boolean unlockSurface0(long window, long view); /** Must be called on Main-Thread */ diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java index 948b29460..342829691 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java @@ -34,91 +34,143 @@ package jogamp.newt.driver.windows; import javax.media.nativewindow.DefaultGraphicsScreen; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.Rectangle; +import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.Screen; public class ScreenDriver extends ScreenImpl { static { DisplayDriver.initSingleton(); + if( Screen.DEBUG ) { + dumpMonitorInfo0(); + } } public ScreenDriver() { } + @Override protected void createNativeImpl() { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); } + @Override protected void closeNativeImpl() { } - private int[] getScreenModeIdx(int idx) { - int[] modeProps = getScreenMode0(screen_idx, idx); - if (null == modeProps || 0 == modeProps.length) { + private final String getAdapterName(int crt_idx) { + return getAdapterName0(crt_idx); + } + private final String getActiveMonitorName(String adapterName, int monitor_idx) { + return getActiveMonitorName0(adapterName, monitor_idx); + } + + private final MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, String adapterName, int crtModeIdx) { + if( null == adapterName ) { return null; } - if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { - throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); + final String activeMonitorName = getActiveMonitorName(adapterName, 0); + final int[] modeProps = null != activeMonitorName ? getMonitorMode0(adapterName, crtModeIdx) : null; + if ( null == modeProps || 0 >= modeProps.length) { + return null; } - return modeProps; + return MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0); } - private int nativeModeIdx; - - protected int[] getScreenModeFirstImpl() { - nativeModeIdx = 0; - return getScreenModeNextImpl(); - } - - protected int[] getScreenModeNextImpl() { - int[] modeProps = getScreenModeIdx(nativeModeIdx); - if (null != modeProps && 0 < modeProps.length) { - nativeModeIdx++; - return modeProps; + @Override + protected void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + int crtIdx = 0; + ArrayHashSet supportedModes = new ArrayHashSet(); + String adapterName = getAdapterName(crtIdx); + while( null != adapterName ) { + int crtModeIdx = 0; + MonitorMode mode; + do { + mode = getMonitorModeImpl(cache, adapterName, crtModeIdx); + if( null != mode ) { + supportedModes.getOrAdd(mode); + // next mode on same monitor + crtModeIdx++; + } + } while( null != mode); + if( 0 < crtModeIdx ) { + // has at least one mode -> add device + final MonitorMode currentMode = getMonitorModeImpl(cache, adapterName, -1); + if ( null != currentMode ) { // enabled + final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx); + // merge monitor-props + supported modes + MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0); + + // next monitor, 1st mode + supportedModes= new ArrayHashSet(); + } + } + crtIdx++; + adapterName = getAdapterName(crtIdx); } - return null; } - - protected ScreenMode getCurrentScreenModeImpl() { - int[] modeProps = getScreenModeIdx(-1); - if (null != modeProps && 0 < modeProps.length) { - return ScreenModeUtil.streamIn(modeProps, 0); + + @Override + protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) { + final String adapterName = getAdapterName(monitor.getId()); + if( null != adapterName ) { + final String activeMonitorName = getActiveMonitorName(adapterName, 0); + if( null != activeMonitorName ) { + final int[] monitorProps = getMonitorDevice0(adapterName, monitor.getId()); + int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT; + return new Rectangle(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]); + } } return null; } - protected boolean setCurrentScreenModeImpl(ScreenMode sm) { - return setScreenMode0(screen_idx, - sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(), - sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(), - sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(), - sm.getMonitorMode().getRefreshRate(), - sm.getRotation()); + @Override + protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) { + return getMonitorModeImpl(null, getAdapterName(monitor.getId()), -1); + } + + @Override + protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) { + return setMonitorMode0(monitor.getId(), + -1, -1, // no fixed position! + mode.getSurfaceSize().getResolution().getWidth(), + mode.getSurfaceSize().getResolution().getHeight(), + mode.getSurfaceSize().getBitsPerPixel(), + (int)mode.getRefreshRate(), // simply cut-off, orig is int + mode.getFlags(), + mode.getRotation()); } + @Override protected int validateScreenIndex(int idx) { - return 0; // big-desktop, only one screen available + return 0; // big-desktop w/ multiple monitor attached, only one screen available } - protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { - virtualOrigin.setX(getOriginX0(screen_idx)); - virtualOrigin.setY(getOriginY0(screen_idx)); - virtualSize.setWidth(getWidthImpl0(screen_idx)); - virtualSize.setHeight(getHeightImpl0(screen_idx)); + @Override + protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) { + vOriginSize.setX(getVirtualOriginX0()); + vOriginSize.setY(getVirtualOriginY0()); + vOriginSize.setWidth(getVirtualWidthImpl0()); + vOriginSize.setHeight(getVirtualHeightImpl0()); } // Native calls - private native int getOriginX0(int screen_idx); - private native int getOriginY0(int screen_idx); - private native int getWidthImpl0(int scrn_idx); - private native int getHeightImpl0(int scrn_idx); + private native int getVirtualOriginX0(); + private native int getVirtualOriginY0(); + private native int getVirtualWidthImpl0(); + private native int getVirtualHeightImpl0(); - private native int[] getScreenMode0(int screen_index, int mode_index); - private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot); + private static native void dumpMonitorInfo0(); + private native String getAdapterName0(int crt_index); + private native String getActiveMonitorName0(String adapterName, int crtModeIdx); + private native int[] getMonitorMode0(String adapterName, int crtModeIdx); + private native int[] getMonitorDevice0(String adapterName, int monitor_index); + private native boolean setMonitorMode0(int monitor_index, int x, int y, int width, int height, int bits, int freq, int flags, int rot); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java index 485d976ec..c569e5fd8 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java @@ -27,13 +27,50 @@ */ package jogamp.newt.driver.x11; -import com.jogamp.newt.ScreenMode; +import java.util.List; + +import jogamp.newt.MonitorModeProps; + +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public interface RandR { - int[] getScreenModeFirstImpl(final long dpy, final int screen_idx); - int[] getScreenModeNextImpl(final long dpy, final int screen_idx); - ScreenMode getCurrentScreenModeImpl(final long dpy, final int screen_idx); - boolean setCurrentScreenModeImpl(final long dpy, final int screen_idx, final ScreenMode screenMode, final int screenModeIdx, final int resolutionIdx); + void dumpInfo(final long dpy, final int screen_idx); + + /** + * Encapsulate initial device query allowing caching of internal data structures. + * Methods covered: + *
      + *
    • {@link #getMonitorDeviceCount(long, ScreenDriver)}
    • + *
    • {@link #getAvailableRotations(long, ScreenDriver, int)}
    • + *
    • {@link #getMonitorModeProps(long, ScreenDriver, int)}
    • + *
    • {@link #getCurrentMonitorModeProps(long, ScreenDriver, int)
    • + *
    • {@link #getMonitorDeviceProps(long, ScreenDriver, List, int, MonitorMode)}
    • + *
    + *

    + * Above methods may be called w/o begin/end, in which case no + * internal data structures can be cached: + *

    + * @param dpy TODO + * @param screen TODO + * @return TODO + */ + boolean beginInitialQuery(long dpy, ScreenDriver screen); + void endInitialQuery(long dpy, ScreenDriver screen); + int getMonitorDeviceCount(final long dpy, final ScreenDriver screen); + int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx); + /** + * + * @param dpy + * @param screen + * @param mode_idx w/o indexing rotation + * @return props w/o actual rotation + */ + int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx); + int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx); + int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx); + int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx); + boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java index ee67bd304..a938b4064 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java @@ -27,139 +27,257 @@ */ package jogamp.newt.driver.x11; +import jogamp.newt.MonitorModeProps; import jogamp.newt.ScreenImpl; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.common.util.VersionNumber; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; public class RandR11 implements RandR { private static final boolean DEBUG = ScreenDriver.DEBUG; - private int[] nrotations; - private int nrotation_index; - private int nres_number; - private int nres_index; - private int[] nrates; - private int nrate_index; - private int nmode_number; + public static VersionNumber version = new VersionNumber(1, 1, 0); + + public static RandR11 createInstance(VersionNumber rAndRVersion) { + if( rAndRVersion.compareTo(version) >= 0 ) { + return new RandR11(); + } + return null; + } + private RandR11() { + } + + @Override + public void dumpInfo(final long dpy, final int screen_idx) { + // NOP + } + + private int widthMM=0, heightMM=0; + private int modeCount = 0; + private int resolutionCount = 0; + private int[][] nrates = null; // [nres_number][nrate_number] + private int[] idx_rate = null, idx_res = null; @Override - public int[] getScreenModeFirstImpl(final long dpy, final int screen_idx) { + public boolean beginInitialQuery(long dpy, ScreenDriver screen) { // initialize iterators and static data - nrotations = getAvailableScreenModeRotations0(dpy, screen_idx); - if(null==nrotations || 0==nrotations.length) { - return null; + final int screen_idx = screen.getIndex(); + resolutionCount = getNumScreenResolutions0(dpy, screen_idx); + if(0==resolutionCount) { + endInitialQuery(dpy, screen); + return false; } - nrotation_index = 0; - nres_number = getNumScreenModeResolutions0(dpy, screen_idx); - if(0==nres_number) { - return null; + nrates = new int[resolutionCount][]; + for(int i=0; i= modeCount ) { + return null; + } + final int screen_idx = screen.getIndex(); + + final int nres_index = idx_res[mode_idx]; + final int nrate_index = idx_rate[mode_idx]; + + final int[] res = getScreenResolution0(dpy, screen_idx, nres_index); if(null==res || 0==res.length) { return null; } if(0>=res[0] || 0>=res[1]) { - throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number); + throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+resolutionCount); + } + if( res[2] > widthMM ) { + widthMM = res[2]; } - int rate = nrates[nrate_index]; + if( res[3] > heightMM ) { + heightMM = res[3]; + } + + int rate = nrates[nres_index][nrate_index]; if(0>=rate) { rate = ScreenImpl.default_sm_rate; if(DEBUG) { System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+ScreenImpl.default_sm_rate); } } - int rotation = nrotations[nrotation_index]; - int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ]; + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; int i = 0; - props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode - props[i++] = 0; // set later for verification of iterator + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; props[i++] = res[0]; // width props[i++] = res[1]; // height - props[i++] = ScreenImpl.default_sm_bpp; // FIXME - props[i++] = res[2]; // widthmm - props[i++] = res[3]; // heightmm - props[i++] = rate; // rate - props[i++] = rotation; - props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element - - nmode_number++; - - // iteration: r -> f -> bpp -> [w x h] - nrotation_index++; - if(nrotation_index == nrotations.length) { - nrotation_index=0; - nrate_index++; - if(null == nrates || nrate_index == nrates.length){ - nres_index++; - if(nres_index == nres_number) { - // done - nrates=null; - nrotations=null; - return null; - } - - nrates = getScreenModeRates0(dpy, screen_idx, nres_index); - if(null==nrates || 0==nrates.length) { - return null; - } - nrate_index = 0; - } + props[i++] = ScreenImpl.default_sm_bpp; // bpp n/a in RandR11 + props[i++] = rate*100; // rate (Hz*100) + props[i++] = 0; // flags; + props[i++] = nres_index; + props[i++] = -1; // rotation placeholder; + if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) { + throw new InternalError("XX"); + } + return props; + } + + @Override + public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) { + if( 0 < crt_idx ) { + // RandR11 only supports 1 CRT + return null; + } + final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_idx); + if( null == currentModeProps) { // disabled + return null; + } + final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, currentModeProps, 0); + final int allModesCount = cache.monitorModes.size(); + final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 + allModesCount]; + int i = 0; + props[i++] = props.length; + props[i++] = crt_idx; + props[i++] = widthMM; + props[i++] = heightMM; + props[i++] = 0; // rotated viewport x + props[i++] = 0; // rotated viewport y + props[i++] = currentMode.getRotatedWidth(); // rotated viewport width + props[i++] = currentMode.getRotatedHeight(); // rotated viewport height + props[i++] = currentMode.getId(); // current mode id + props[i++] = currentMode.getRotation(); + for(int j=0; jnres_idx) { + return null; + } + if(nres_idx>=resNumber) { + throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber); + } + res = getScreenResolution0(dpy, screen_idx, nres_idx); + if(null==res || 0==res.length) { + return null; + } + if(0>=res[0] || 0>=res[1]) { + throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber); + } + } finally { + freeScreenConfiguration0(screenConfigHandle); + } + int[] props = new int[4]; + int i = 0; + props[i++] = 0; + props[i++] = 0; + props[i++] = res[0]; // width + props[i++] = res[1]; // height + return props; + } + @Override - public ScreenMode getCurrentScreenModeImpl(final long dpy, final int screen_idx) { + public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) { + if( 0 < crt_idx ) { + // RandR11 only supports 1 CRT + return null; + } + final int screen_idx = screen.getIndex(); long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); if(0 == screenConfigHandle) { return null; } int[] res; int rate, rot; + final int nres_idx; try { - int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); + int resNumber = getNumScreenResolutions0(dpy, screen_idx); if(0==resNumber) { return null; } - int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle); - if(0>resIdx) { + nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle); + if(0>nres_idx) { return null; } - if(resIdx>=resNumber) { - throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber); + if(nres_idx>=resNumber) { + throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber); } - res = getScreenModeResolution0(dpy, screen_idx, resIdx); + res = getScreenResolution0(dpy, screen_idx, nres_idx); if(null==res || 0==res.length) { return null; } if(0>=res[0] || 0>=res[1]) { - throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber); + throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber); } rate = getCurrentScreenRate0(screenConfigHandle); if(0>rate) { @@ -172,40 +290,42 @@ public class RandR11 implements RandR { } finally { freeScreenConfiguration0(screenConfigHandle); } - int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL]; + int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ]; int i = 0; - props[i++] = 0; // set later for verification of iterator + props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL; props[i++] = res[0]; // width props[i++] = res[1]; // height - props[i++] = ScreenImpl.default_sm_bpp; // FIXME - props[i++] = res[2]; // widthmm - props[i++] = res[3]; // heightmm - props[i++] = rate; // rate + props[i++] = ScreenImpl.default_sm_bpp; + props[i++] = rate*100; // rate (Hz*100) + props[i++] = 0; // flags; + props[i++] = nres_idx; // mode_idx; props[i++] = rot; - props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count - return ScreenModeUtil.streamIn(props, 0); + if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) { + throw new InternalError("XX"); + } + return props; } @Override - public boolean setCurrentScreenModeImpl(final long dpy, final int screen_idx, final ScreenMode screenMode, final int screenModeIdx, final int resolutionIdx) { + public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) { final long t0 = System.currentTimeMillis(); boolean done = false; + final int screen_idx = screen.getIndex(); long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx); if(0 == screenConfigHandle) { return Boolean.valueOf(done); } try { - int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); - if(0>resolutionIdx || resolutionIdx>=resNumber) { - throw new RuntimeException("Invalid resolution index: ! 0 < "+resolutionIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode); - } - - final int f = screenMode.getMonitorMode().getRefreshRate(); - final int r = screenMode.getRotation(); + final int resId = mode.getId(); + if(0>resId || resId>=resolutionCount) { + throw new RuntimeException("Invalid resolution index: ! 0 < "+resId+" < "+resolutionCount+", "+monitor+", "+mode); + } + final int f = (int)mode.getRefreshRate(); // simply cut-off, orig is int + final int r = mode.getRotation(); - if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resolutionIdx, f, r) ) { + if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resId, f, r) ) { while(!done && System.currentTimeMillis()-t0 < ScreenImpl.SCREEN_MODE_CHANGE_TIMEOUT) { - done = setCurrentScreenModePollEnd0(dpy, screen_idx, resolutionIdx, f, r); + done = setCurrentScreenModePollEnd0(dpy, screen_idx, resId, f, r); if(!done) { try { Thread.sleep(10); } catch (InterruptedException e) { } } @@ -218,14 +338,14 @@ public class RandR11 implements RandR { } /** @return int[] { rot1, .. } */ - private static native int[] getAvailableScreenModeRotations0(long display, int screen_index); + private static native int[] getAvailableScreenRotations0(long display, int screen_index); - private static native int getNumScreenModeResolutions0(long display, int screen_index); + private static native int getNumScreenResolutions0(long display, int screen_index); /** @return int[] { width, height, widthmm, heightmm } */ - private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index); + private static native int[] getScreenResolution0(long display, int screen_index, int mode_index); - private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index); + private static native int[] getScreenRates0(long display, int screen_index, int mode_index); private static native long getScreenConfiguration0(long display, int screen_index); private static native void freeScreenConfiguration0(long screenConfiguration); diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java index 24c9806af..d10591381 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java +++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java @@ -27,25 +27,283 @@ */ package jogamp.newt.driver.x11; -import com.jogamp.newt.ScreenMode; +import java.util.Iterator; +import jogamp.newt.MonitorModeProps; + +import com.jogamp.common.util.IntLongHashMap; +import com.jogamp.common.util.VersionNumber; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; + +/** + * Mapping details: + *
    + * MonitorMode.id   == XRR mode-id (not index)
    + * MonitorDevice.id == XRR monitor-idx (not id)
    + * 
    + */ public class RandR13 implements RandR { + private static final boolean DEBUG = ScreenDriver.DEBUG; + + public static VersionNumber version = new VersionNumber(1, 3, 0); - public int[] getScreenModeFirstImpl(final long dpy, final int screen_idx) { + public static RandR13 createInstance(VersionNumber rAndRVersion) { + if( rAndRVersion.compareTo(version) >= 0 ) { + return new RandR13(); + } return null; + } + private RandR13() { + } + + @Override + public void dumpInfo(final long dpy, final int screen_idx) { + long screenResources = getScreenResources0(dpy, screen_idx); + if(0 == screenResources) { + return; + } + try { + dumpInfo0(dpy, screen_idx, screenResources); + } finally { + freeScreenResources0(screenResources); + } + } + + long sessionScreenResources = 0; + IntLongHashMap crtInfoHandleMap = null; + + @Override + public boolean beginInitialQuery(long dpy, ScreenDriver screen) { + final int screen_idx = screen.getIndex(); + sessionScreenResources = getScreenResources0(dpy, screen_idx); + if( 0 != sessionScreenResources ) { + crtInfoHandleMap = new IntLongHashMap(); + crtInfoHandleMap.setKeyNotFoundValue(0); + return true; + } else { + return false; + } + } + + @Override + public void endInitialQuery(long dpy, ScreenDriver screen) { + if( null != crtInfoHandleMap ) { + for(Iterator iter = crtInfoHandleMap.iterator(); iter.hasNext(); ) { + final IntLongHashMap.Entry entry = iter.next(); + freeMonitorInfoHandle0(entry.value); + } + crtInfoHandleMap.clear(); + crtInfoHandleMap = null; + } + if( 0 != sessionScreenResources ) { + freeScreenResources0( sessionScreenResources ); + sessionScreenResources = 0; + } } - public int[] getScreenModeNextImpl(final long dpy, final int screen_idx) { - return null; + + private final long getScreenResourceHandle(final long dpy, final int screen_idx) { + if( 0 != sessionScreenResources ) { + return sessionScreenResources; + } + return getScreenResources0(dpy, screen_idx); + } + private final void releaseScreenResourceHandle(final long screenResourceHandle) { + if( 0 == sessionScreenResources ) { + freeScreenResources0( screenResourceHandle ); + } } - public ScreenMode getCurrentScreenModeImpl(final long dpy, final int screen_idx) { - return null; + + private final long getMonitorInfoHandle(final long dpy, final int screen_idx, long screenResources, final int monitor_idx) { + if( null != crtInfoHandleMap ) { + long h = crtInfoHandleMap.get(monitor_idx); + if( 0 == h ) { + h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx); + crtInfoHandleMap.put(monitor_idx, h); + } + return h; + } else { + return getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx); + } } + private final void releaseMonitorInfoHandle(final long monitorInfoHandle) { + if( null == crtInfoHandleMap ) { + freeMonitorInfoHandle0(monitorInfoHandle); + } + } - public boolean setCurrentScreenModeImpl(final long dpy, final int screen_idx, final ScreenMode screenMode, final int screenModeIdx, final int resolutionIdx) { - return false; + @Override + public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + return getMonitorDeviceCount0(screenResources); + } finally { + releaseScreenResourceHandle(screenResources); + } } + @Override + public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx); + try { + final int[] availRotations = getAvailableRotations0(monitorInfo); + if(null==availRotations || 0==availRotations.length) { + return null; + } + return availRotations; + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + } finally { + releaseScreenResourceHandle(screenResources); + } + } + + @Override + public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + return getMonitorMode0(screenResources, mode_idx); + } finally { + releaseScreenResourceHandle(screenResources); + } + } + + @Override + public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx); + try { + return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_idx); + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + } finally { + releaseScreenResourceHandle(screenResources); + } + } + + @Override + public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx); + try { + return getMonitorViewport0(monitorInfo); + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + } finally { + releaseScreenResourceHandle(screenResources); + } + } + + @Override + public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx); + try { + return getMonitorCurrentMode0(screenResources, monitorInfo); + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + } finally { + releaseScreenResourceHandle(screenResources); + } + } + + @Override + public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + final boolean res; + try { + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId()); + try { + res = setMonitorMode0(dpy, screenResources, monitorInfo, monitor.getId(), mode.getId(), mode.getRotation(), + -1, -1); // no fixed position! + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + } finally { + releaseScreenResourceHandle(screenResources); + } + /*** + * TODO: Would need a complete re-layout of crt positions, + * which is _not_ implicit by XRandR .. sadly. + * + if( res ) { + updateScreenViewport(dpy, screen, monitor); + } */ + return res; + } + + /** See above .. + private final void updateScreenViewport(final long dpy, final ScreenDriver screen, MonitorDevice monitor) { + final int screen_idx = screen.getIndex(); + final long screenResources = getScreenResourceHandle(dpy, screen_idx); + try { + RectangleImmutable newViewp = null; + final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId()); + try { + final int[] vprops = getMonitorViewport0(monitorInfo); + if( null != vprops ) { + newViewp = new Rectangle(vprops[0], vprops[1], vprops[2], vprops[3]); + } + System.err.println("XXX setScreenViewport: newVp "+newViewp); + } finally { + releaseMonitorInfoHandle(monitorInfo); + } + if( null != newViewp ) { + final List monitors = screen.getMonitorDevices(); + final ArrayList viewports = new ArrayList(); + for(int i=0; i "+newScrnViewp); + setScreenViewport0(dpy, screen_idx, screenResources, newScrnViewp.getX(), newScrnViewp.getY(), newScrnViewp.getWidth(), newScrnViewp.getHeight()); + } + } finally { + dumpInfo0(dpy, screen_idx, screenResources); + releaseScreenResourceHandle(screenResources); + } + } */ + private static native long getScreenResources0(long display, int screen_index); - private static native void freeScreenResources0(long screenConfiguration); + private static native void freeScreenResources0(long screenResources); + private static native void dumpInfo0(long display, int screen_index, long screenResources); + + private static native int getMonitorDeviceCount0(long screenResources); + + private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int monitor_index); + private static native void freeMonitorInfoHandle0(long monitorInfoHandle); + + private static native int[] getAvailableRotations0(long monitorInfo); + private static native int[] getMonitorViewport0(long monitorInfo); + private static native int[] getMonitorCurrentMode0(long monitorInfo); + + private static native int[] getMonitorMode0(long screenResources, int mode_index); + private static native int[] getMonitorCurrentMode0(long screenResources, long monitorInfo); + private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int monitor_idx); + private static native boolean setMonitorMode0(long display, long screenResources, long monitorInfo, int monitor_idx, int mode_id, int rotation, int x, int y); + private static native boolean setScreenViewport0(long display, int screen_index, long screenResources, int x, int y, int width, int height); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java index cd8da9b60..ba22a6ce4 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java @@ -33,23 +33,29 @@ */ package jogamp.newt.driver.x11; +import java.util.ArrayList; import java.util.List; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.util.Rectangle; import jogamp.nativewindow.x11.X11Util; +import jogamp.newt.Debug; import jogamp.newt.DisplayImpl; +import jogamp.newt.MonitorModeProps; import jogamp.newt.DisplayImpl.DisplayRunnable; import jogamp.newt.ScreenImpl; +import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.VersionNumber; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; -import com.jogamp.newt.ScreenMode; - -public class ScreenDriver extends ScreenImpl { +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; +public class ScreenDriver extends ScreenImpl { + protected static final boolean DEBUG_TEST_RANDR13_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableRandR13", true); + static { DisplayDriver.initSingleton(); } @@ -57,12 +63,13 @@ public class ScreenDriver extends ScreenImpl { public ScreenDriver() { } + @Override protected void createNativeImpl() { // validate screen index Long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { public Long run(long dpy) { return new Long(GetScreen0(dpy, screen_idx)); - } } ); + } } ); if (handle.longValue() == 0) { throw new RuntimeException("Error creating screen: " + screen_idx); } @@ -73,73 +80,116 @@ public class ScreenDriver extends ScreenImpl { int v[] = getRandRVersion0(dpy); randrVersion = new VersionNumber(v[0], v[1], 0); } - if( DEBUG ) { - System.err.println("RandR "+randrVersion); + { + final RandR13 rAndR13 = DEBUG_TEST_RANDR13_DISABLED ? null : RandR13.createInstance(randrVersion); + if( null != rAndR13 ) { + rAndR = rAndR13; + } else { + rAndR = RandR11.createInstance(randrVersion); + } } - if( !randrVersion.isZero() ) { - rAndR = new RandR11(); - } else { - rAndR = null; + if( DEBUG ) { + System.err.println("RandR "+randrVersion+", "+rAndR); + rAndR.dumpInfo(dpy, screen_idx); } } + @Override protected void closeNativeImpl() { } private VersionNumber randrVersion; private RandR rAndR; - + @Override - protected int[] getScreenModeFirstImpl() { - if( null == rAndR ) { return null; } - - return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - public int[] run(long dpy) { - return rAndR.getScreenModeFirstImpl(dpy, screen_idx); - } } ); + protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) { + if( null == rAndR ) { return; } + final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice(); + device.lock(); + try { + if( rAndR.beginInitialQuery(device.getHandle(), this) ) { + try { + final int crtCount = rAndR.getMonitorDeviceCount(device.getHandle(), this); + + // Gather all available rotations + final ArrayHashSet availableRotations = new ArrayHashSet(); + for(int i = 0; i < crtCount; i++) { + final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, i); + if( null != rotations ) { + final List rotationList = new ArrayList(rotations.length); + for(int j=0; j 0 ) { + for(int i = 0; i < crtCount; i++) { + final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, i); + if( null != monitorProps ) { // enabled + MonitorModeProps.streamInMonitorDevice(null, cache, this, monitorProps, 0); + } + } + } + } finally { + rAndR.endInitialQuery(device.getHandle(), this); + } + } + } finally { + device.unlock(); + } } @Override - protected int[] getScreenModeNextImpl() { - if( null == rAndR ) { return null; } - - // assemble: w x h x bpp x f x r - return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - public int[] run(long dpy) { - return rAndR.getScreenModeNextImpl(dpy, screen_idx); - } } ); + protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) { + final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice(); + device.lock(); + try { + int[] viewportProps = rAndR.getMonitorDeviceViewport(device.getHandle(), this, monitor.getId()); + return new Rectangle(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]); + } finally { + device.unlock(); + } } - + @Override - protected ScreenMode getCurrentScreenModeImpl() { + protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) { if( null == rAndR ) { return null; } - return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - public ScreenMode run(long dpy) { - return rAndR.getCurrentScreenModeImpl(dpy, screen_idx); + return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + public MonitorMode run(long dpy) { + final int[] currentModeProps = rAndR.getCurrentMonitorModeProps(dpy, ScreenDriver.this, monitor.getId()); + return MonitorModeProps.streamInMonitorMode(null, null, currentModeProps, 0); } } ); } @Override - protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { + protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) { if( null == rAndR ) { return false; } - final List screenModes = this.getScreenModesOrig(); - final int screenModeIdx = screenModes.indexOf(screenMode); - if(0>screenModeIdx) { - throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); - } final long t0 = System.currentTimeMillis(); boolean done = runWithTempDisplayHandle( new DisplayImpl.DisplayRunnable() { public Boolean run(long dpy) { - final int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); - return Boolean.valueOf( rAndR.setCurrentScreenModeImpl(dpy, screen_idx, screenMode, screenModeIdx, resIdx) ); + return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) ); } }).booleanValue(); if(DEBUG || !done) { System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ - (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode); + (System.currentTimeMillis()-t0)+"ms; "+monitor.getCurrentMode()+" -> "+mode); } return done; } @@ -149,6 +199,7 @@ public class ScreenDriver extends ScreenImpl { return new Boolean(X11Util.XineramaIsEnabled(dpy)); } }; + @Override protected int validateScreenIndex(final int idx) { final DisplayDriver x11Display = (DisplayDriver) getDisplay(); final Boolean r = x11Display.isXineramaEnabled(); @@ -159,13 +210,14 @@ public class ScreenDriver extends ScreenImpl { } } - protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) { + @Override + protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) { runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { public Object run(long dpy) { - virtualOrigin.setX(0); - virtualOrigin.setY(0); - virtualSize.setWidth(getWidth0(dpy, screen_idx)); - virtualSize.setHeight(getHeight0(dpy, screen_idx)); + vOriginSize.setX(0); + vOriginSize.setY(0); + vOriginSize.setWidth(getWidth0(dpy, screen_idx)); + vOriginSize.setHeight(getHeight0(dpy, screen_idx)); return null; } } ); } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index c0552216e..1c7064a66 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -285,47 +285,32 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic [pool release]; } -static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { +static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) { NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; + if( screen_idx<0 || screen_idx>=[screens count] ) { + if( cap ) { + screen_idx=0; + } else { + return NULL; + } + } return (NSScreen *) [screens objectAtIndex: screen_idx]; } -/* - * Class: jogamp_newt_driver_macosx_ScreenDriver - * Method: getWidthImpl - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getWidthImpl0 - (JNIEnv *env, jclass clazz, jint screen_idx) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); - NSRect rect = [screen frame]; - - [pool release]; - - return (jint) (rect.size.width); -} - -/* - * Class: jogamp_newt_driver_macosx_ScreenDriver - * Method: getHeightImpl - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getHeightImpl0 - (JNIEnv *env, jclass clazz, jint screen_idx) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); - NSRect rect = [screen frame]; - - [pool release]; - - return (jint) (rect.size.height); +static NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) { + NSArray *screens = [NSScreen screens]; + int i; + for(i=[screens count]-1; i>=0; i--) { + NSScreen * screen = (NSScreen *) [screens objectAtIndex: i]; + NSRect frame = [screen frame]; + if( x >= frame.origin.x && + y >= frame.origin.y && + x < frame.origin.x + frame.size.width && + y < frame.origin.y + frame.size.height ) { + return screen; + } + } + return (NSScreen *) [screens objectAtIndex: 0]; } static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { @@ -362,11 +347,11 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) /* * Class: jogamp_newt_driver_macosx_ScreenDriver - * Method: getScreenSizeMM0 + * Method: getMonitorProps0 * Signature: (I)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenSizeMM0 - (JNIEnv *env, jobject obj, jint scrn_idx) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0 + (JNIEnv *env, jobject obj, jint crt_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -376,33 +361,46 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree timespec_now(&t0); #endif - NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL); + fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL); #endif - + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false); + if( NULL == screen ) { + [pool release]; + return NULL; + } CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL); + fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL); #endif - CGSize screenDim = CGDisplayScreenSize(display); + CGSize sizeMM = CGDisplayScreenSize(display); #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL); + fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL); #endif - jint prop[ 2 ]; - prop[0] = (jint) screenDim.width; - prop[1] = (jint) screenDim.height; - - jintArray properties = (*env)->NewIntArray(env, 2); + CGRect bounds = CGDisplayBounds (display); + + jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES; + jint prop[ propCount ]; + int offset = 0; + prop[offset++] = propCount; + prop[offset++] = crt_idx; + prop[offset++] = (jint) sizeMM.width; + prop[offset++] = (jint) sizeMM.height; + prop[offset++] = (jint) bounds.origin.x; // rotated viewport x + prop[offset++] = (jint) bounds.origin.y; // rotated viewport y + prop[offset++] = (jint) bounds.size.width; // rotated viewport width + prop[offset++] = (jint) bounds.size.height; // rotated viewport height + + jintArray properties = (*env)->NewIntArray(env, propCount); if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2"); + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount); } - (*env)->SetIntArrayRegion(env, properties, 0, 2, prop); + (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop); [pool release]; @@ -411,16 +409,19 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree /* * Class: jogamp_newt_driver_macosx_ScreenDriver - * Method: getScreenMode0 - * Signature: (IIII)[I + * Method: getMonitorMode0 + * Signature: (II)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenMode0 - (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0 + (JNIEnv *env, jobject obj, jint crt_idx, jint mode_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL; - NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false); + if( NULL == screen ) { + [pool release]; + return NULL; + } CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); CFArrayRef availableModes = CGDisplayAvailableModes(display); @@ -429,12 +430,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree CFDictionaryRef mode = NULL; int currentCCWRot = (int)CGDisplayRotation(display); jint ccwRot = 0; + int nativeId = 0; #ifdef VERBOSE_ON if(0 >= mode_idx) { // only for current mode (-1) and first mode (scanning) DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n", - (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); + (int)crt_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); } #endif @@ -443,16 +445,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n", (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); [pool release]; - return (*env)->NewIntArray(env, 0); + return NULL; } else if(-1 < mode_idx) { // only at initialization time, where index >= 0 - prop_num++; // add 1st extra prop, mode_idx - mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); + nativeId = mode_idx / ROTMODES_PER_REALMODE; ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; + mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId); } else { // current mode mode = CGDisplayCurrentMode(display); ccwRot = currentCCWRot; + CFRange range = CFRangeMake (0, numberOfAvailableModes); + nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode); } // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef @@ -466,36 +470,30 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree mHeight = tempWidth; } - jint prop[ prop_num ]; + jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ]; int propIndex = 0; - int propIndexRes = 0; - if( -1 < mode_idx ) { - prop[propIndex++] = mode_idx; - } int refreshRate = CGDDGetModeRefreshRate(mode); int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8) - prop[propIndex++] = 0; // set later for verification of iterator - propIndexRes = propIndex; + prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL; prop[propIndex++] = mWidth; prop[propIndex++] = mHeight; prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); - prop[propIndex++] = widthMM; - prop[propIndex++] = heightMM; - prop[propIndex++] = fRefreshRate; + prop[propIndex++] = fRefreshRate * 100; // Hz*100 + prop[propIndex++] = 0; // flags + prop[propIndex++] = nativeId; prop[propIndex++] = ccwRot; - prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL - DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n", + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n", (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, - (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], - (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]); + (int)prop[1], (int)prop[2], (int)prop[3], + (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]); - jintArray properties = (*env)->NewIntArray(env, prop_num); + jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL); if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num); + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL); } - (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop); + (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop); // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef [pool release]; @@ -505,36 +503,47 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree /* * Class: jogamp_newt_driver_macosx_ScreenDriver - * Method: setScreenMode0 - * Signature: (II)Z + * Method: setMonitorMode0 + * Signature: (III)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setScreenMode0 - (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx) +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0 + (JNIEnv *env, jobject object, jint crt_idx, jint nativeId, jint ccwRot) { jboolean res = JNI_TRUE; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false); + if( NULL == screen ) { + [pool release]; + return JNI_FALSE; + } CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); CFArrayRef availableModes = CGDisplayAvailableModes(display); -#ifdef VERBOSE_ON CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); +#ifdef VERBOSE_ON CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; #endif - CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); - // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef - int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; - DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n", - (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), nativeID %d, rot %d ccw, avail: %d/%d\n", + (int)crt_idx, screen, (void*)(intptr_t)display, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + + CFDictionaryRef mode = NULL; - if(ccwRot!=0) { + if( 0 != ccwRot ) { // FIXME: How to rotate the display/screen on OSX programmatically ? DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot); res = JNI_FALSE; + } else { + if( numberOfAvailableModes <= nativeId ) { + res = JNI_FALSE; + } else { + mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId); + // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef + } } - if(JNI_TRUE == res) { + + if( NULL != mode ) { CGError err = CGDisplaySwitchToMode(display, mode); if(kCGErrorSuccess != err) { DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err); @@ -593,21 +602,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 /** * Class: jogamp_newt_driver_macosx_WindowDriver * Method: createView0 - * Signature: (IIIIZI)J + * Signature: (IIIIZ)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0 (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, - jboolean fullscreen, jint screen_idx) + jboolean fullscreen) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, fs %d, screenidx %d (START)\n", - (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, (int)screen_idx); + DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, fs %d (START)\n", + (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen); - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y); NSRect rectWin; if (fullscreen) { @@ -634,24 +640,21 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0 * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: createWindow0 - * Signature: (IIIIZIIIJ)J + * Signature: (IIIIZIIJ)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0 (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, - jboolean fullscreen, jint styleMask, jint bufferingType, jint screen_idx, jlong jview) + jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* myView = (NewtView*) (intptr_t) jview ; DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n", (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, - (int)styleMask, (int)bufferingType, (int)screen_idx, myView); + (int)styleMask, (int)bufferingType, myView); (void)myView; - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y); NSRect rectWin; if (fullscreen) { @@ -670,7 +673,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType defer: YES - screen: myScreen isFullscreenWindow: fullscreen]; // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]); @@ -687,26 +689,23 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: initWindow0 - * Signature: (JJIIIIZZZIJ)V + * Signature: (JJIIIIZZZJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, - jboolean opaque, jboolean fullscreen, jboolean visible, jint screen_idx, jlong jview) + jboolean opaque, jboolean fullscreen, jboolean visible, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); NewtView* myView = (NewtView*) (intptr_t) jview ; - DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, screenidx %d, view %p (START)\n", + DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, view %p (START)\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, - (int) opaque, (int)fullscreen, (int)visible, (int)screen_idx, myView); + (int) opaque, (int)fullscreen, (int)visible, myView); - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx]; - NSRect rectWin; + NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y); + NSRect rectWin; if (fullscreen) { rectWin = [myScreen frame]; x = 0; diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 09f4a1fd3..c9d53f53b 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -128,7 +128,6 @@ styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType defer: (BOOL) deferCreation - screen:(NSScreen *)screen isFullscreenWindow:(BOOL)isfs; #ifdef DBG_LIFECYCLE - (void) release; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 005e82d72..35d3ffbc5 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -439,14 +439,12 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType defer: (BOOL) deferCreation - screen:(NSScreen *)screen isFullscreenWindow:(BOOL)isfs { id res = [super initWithContentRect: contentRect styleMask: windowStyle backing: bufferingType - defer: deferCreation - screen: screen]; + defer: deferCreation]; isFullscreenWindow = isfs; // Why is this necessary? Without it we don't get any of the // delegate methods like resizing and window movement. diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h index bb782910e..110f1c493 100644 --- a/src/newt/native/ScreenMode.h +++ b/src/newt/native/ScreenMode.h @@ -33,12 +33,17 @@ #ifndef _SCREEN_MODE_H #define _SCREEN_MODE_H -#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */ -#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */ -#define NUM_MONITOR_MODE_PROPERTIES 3 /* ScreenSizeMM[width, height], refresh-rate */ -#define NUM_SCREEN_MODE_PROPERTIES 1 /* rotation */ +#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */ +#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */ +#define NUM_SIZEANDRATE_PROPERTIES 2 /* refresh-rate, flags */ +#define NUM_MONITOR_MODE_PROPERTIES 2 /* id, rotation */ -#define NUM_SCREEN_MODE_PROPERTIES_ALL 8 /* count + the above */ +#define NUM_MONITOR_MODE_PROPERTIES_ALL 8 /* count + the above */ + +#define MIN_MONITOR_DEVICE_PROPERTIES 11 /* count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ */ + +#define FLAG_INTERLACE ( 1 << 0 ) +#define FLAG_DOUBLESCAN ( 1 << 1 ) #endif diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index 4755c4fc5..d9ee5fd1f 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -38,8 +38,9 @@ #define FLAG_HAS_PARENT ( 1 << 8 ) #define FLAG_IS_UNDECORATED ( 1 << 9 ) #define FLAG_IS_FULLSCREEN ( 1 << 10 ) -#define FLAG_IS_ALWAYSONTOP ( 1 << 11 ) -#define FLAG_IS_VISIBLE ( 1 << 12 ) +#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 11 ) +#define FLAG_IS_ALWAYSONTOP ( 1 << 12 ) +#define FLAG_IS_VISIBLE ( 1 << 13 ) #define TST_FLAG_CHANGE_PARENTING(f) ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) ) #define TST_FLAG_CHANGE_DECORATION(f) ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) ) @@ -47,11 +48,11 @@ #define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) ) #define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) -#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) ) -#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) -#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) -#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) -#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) -#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) +#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) ) +#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) +#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) +#define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) ) +#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) +#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) #endif diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 5c1115592..7ede3a20d 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -101,6 +101,9 @@ #ifndef DISPLAY_DEVICE_ACTIVE #define DISPLAY_DEVICE_ACTIVE 0x00000001 #endif +#ifndef DM_INTERLACED +#define DM_INTERLACED 2 +#endif #include "jogamp_newt_driver_windows_DisplayDriver.h" #include "jogamp_newt_driver_windows_ScreenDriver.h" @@ -1116,11 +1119,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: getOriginX0 - * Signature: (I)I + * Method: getVirtualOriginX0 + * Signature: ()I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0 - (JNIEnv *env, jobject obj, jint scrn_idx) +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginX0 + (JNIEnv *env, jobject obj) { if( GetSystemMetrics( SM_CMONITORS) > 1) { return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN); @@ -1131,11 +1134,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0 /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: getOriginY0 - * Signature: (I)I + * Method: getVirtualOriginY0 + * Signature: ()I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0 - (JNIEnv *env, jobject obj, jint scrn_idx) +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginY0 + (JNIEnv *env, jobject obj) { if( GetSystemMetrics( SM_CMONITORS ) > 1) { return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN); @@ -1146,11 +1149,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0 /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: getWidthImpl - * Signature: (I)I + * Method: getVirtualWidthImpl + * Signature: ()I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl0 - (JNIEnv *env, jobject obj, jint scrn_idx) +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualWidthImpl0 + (JNIEnv *env, jobject obj) { if( GetSystemMetrics( SM_CMONITORS) > 1) { return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN); @@ -1161,11 +1164,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: getHeightImpl - * Signature: (I)I + * Method: getVirtualHeightImpl + * Signature: ()I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getHeightImpl0 - (JNIEnv *env, jobject obj, jint scrn_idx) +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualHeightImpl0 + (JNIEnv *env, jobject obj) { if( GetSystemMetrics( SM_CMONITORS ) > 1) { return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN); @@ -1217,65 +1220,137 @@ static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) { return native; } -/* -static void NewtScreen_scanDisplayDevices() { - DISPLAY_DEVICE device; - int i = 0; - LPCTSTR name; - while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) { - DBG_PRINT("*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) ); - i++; +static LPCTSTR NewtScreen_getAdapterName(DISPLAY_DEVICE * device, int crt_idx) { + memset(device, 0, sizeof(DISPLAY_DEVICE)); + device->cb = sizeof(DISPLAY_DEVICE); + if( FALSE == EnumDisplayDevices(NULL, crt_idx, device, 0) ) { + DBG_PRINT("*** WindowsWindow: getAdapterName.EnumDisplayDevices(crt_idx %d) -> FALSE\n", crt_idx); + return NULL; } -}*/ -static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) { - device->cb = sizeof(DISPLAY_DEVICE); - if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) { - DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx); + if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) { return NULL; } - if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) { - DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx); + return device->DeviceName; +} + +static LPCTSTR NewtScreen_getMonitorName(LPCTSTR adapterName, DISPLAY_DEVICE * device, int monitor_idx, BOOL onlyActive) { + memset(device, 0, sizeof(DISPLAY_DEVICE)); + device->cb = sizeof(DISPLAY_DEVICE); + if( 0 == monitor_idx ) { + if( FALSE == EnumDisplayDevices(adapterName, monitor_idx, device, 0) ) { + DBG_PRINT("*** WindowsWindow: getDisplayName.EnumDisplayDevices(monitor_idx %d).adapter -> FALSE\n", monitor_idx); + return NULL; + } + } + + if( onlyActive && 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) { + DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(monitor_idx %d).display\n", monitor_idx); + return NULL; + } + if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) { return NULL; } return device->DeviceName; } +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_dumpMonitorInfo0 + (JNIEnv *env, jclass clazz) +{ + DISPLAY_DEVICE aDevice, dDevice; + int i = 0, j; + LPCTSTR aName, dName; + while(NULL != (aName = NewtScreen_getAdapterName(&aDevice, i))) { + fprintf(stderr, "*** [%d]: <%s> flags 0x%X active %d\n", i, aName, aDevice.StateFlags, ( 0 != ( aDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) ); + j=0; + while(NULL != (dName = NewtScreen_getMonitorName(aName, &dDevice, j, FALSE))) { + fprintf(stderr, "*** [%d][%d]: <%s> flags 0x%X active %d\n", i, j, dName, dDevice.StateFlags, ( 0 != ( dDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) ); + j++; + } + i++; + } +} + static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) { return CreateDC("DISPLAY", displayDeviceName, NULL, NULL); } /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: getScreenMode0 - * Signature: (II)[I + * Method: getAdapterName0 + * Signature: (I)Ljava/lang/String; */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScreenMode0 - (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) +JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getAdapterName0 + (JNIEnv *env, jobject obj, jint crt_idx) { DISPLAY_DEVICE device; - int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL; - LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx); - if(NULL == deviceName) { - DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx); - return (*env)->NewIntArray(env, 0); + LPCTSTR adapterName = NewtScreen_getAdapterName(&device, crt_idx); + DBG_PRINT("*** WindowsWindow: getAdapterName(crt_idx %d) -> %s, active %d\n", crt_idx, + (NULL==adapterName?"nil":adapterName), 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE )); + if(NULL == adapterName) { + return NULL; } +#ifdef UNICODE + return (*env)->NewString(env, adapterName, wcslen(adapterName)); +#else + return (*env)->NewStringUTF(env, adapterName); +#endif +} + +/* + * Class: jogamp_newt_driver_windows_ScreenDriver + * Method: getActiveMonitorName0 + * Signature: (Ljava/lang/String;I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getActiveMonitorName0 + (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx) +{ + DISPLAY_DEVICE device; + LPCTSTR monitorName; +#ifdef UNICODE + LPCTSTR adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName); + monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE); + DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName)); + free((void*) adapterName); +#else + LPCTSTR adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL); + monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE); + DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName)); + (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName); +#endif + if(NULL == monitorName) { + return NULL; + } +#ifdef UNICODE + return (*env)->NewString(env, monitorName, wcslen(monitorName)); +#else + return (*env)->NewStringUTF(env, monitorName); +#endif +} +/* + * Class: jogamp_newt_driver_windows_ScreenDriver + * Method: getMonitorMode0 + * Signature: (Ljava/lang/String;I)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorMode0 + (JNIEnv *env, jobject obj, jstring jAdapterName, jint mode_idx) +{ + DISPLAY_DEVICE device; + LPCTSTR adapterName; + { +#ifdef UNICODE + adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName); +#else + adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL); +#endif + } int devModeID; - int widthmm, heightmm; if(-1 < mode_idx) { - // only at initialization time, where index >= 0 - HDC hdc = NewtScreen_createDisplayDC(deviceName); - widthmm = GetDeviceCaps(hdc, HORZSIZE); - heightmm = GetDeviceCaps(hdc, VERTSIZE); - DeleteDC(hdc); devModeID = (int) mode_idx; - prop_num++; // add 1st extra prop, mode_idx } else { - widthmm = 0; - heightmm = 0; devModeID = ENUM_CURRENT_SETTINGS; } @@ -1283,11 +1358,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); - if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) { - DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID); + int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE); + DBG_PRINT("*** WindowsWindow: getMonitorMode.EnumDisplaySettingsEx(%s, mode_idx %d/%d) -> %d\n", adapterName, mode_idx, devModeID, res); +#ifdef UNICODE + free((void*) adapterName); +#else + (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName); +#endif + + if (0 == res) { return (*env)->NewIntArray(env, 0); } - + // swap width and height, since Windows reflects rotated dimension, we don't if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) { int tempWidth = dm.dmPelsWidth; @@ -1295,43 +1377,110 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre dm.dmPelsHeight = tempWidth; } - jint prop[ prop_num ]; + int flags = 0; + if( 0 != ( dm.dmDisplayFlags & DM_INTERLACED ) ) { + flags |= FLAG_INTERLACE; + } + + jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ]; int propIndex = 0; - if( -1 < mode_idx ) { - prop[propIndex++] = mode_idx; - } - prop[propIndex++] = 0; // set later for verification of iterator + prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL; prop[propIndex++] = dm.dmPelsWidth; prop[propIndex++] = dm.dmPelsHeight; prop[propIndex++] = dm.dmBitsPerPel; - prop[propIndex++] = widthmm; - prop[propIndex++] = heightmm; - prop[propIndex++] = dm.dmDisplayFrequency; + prop[propIndex++] = dm.dmDisplayFrequency * 100; // Hz*100 + prop[propIndex++] = flags; + prop[propIndex++] = 0; // not bound to id prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation); - prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL - jintArray properties = (*env)->NewIntArray(env, prop_num); + jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL); if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num); + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL); } - (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop); + (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop); return properties; } /* * Class: jogamp_newt_driver_windows_ScreenDriver - * Method: setScreenMode0 - * Signature: (IIIIII)Z + * Method: getMonitorDevice0 + * Signature: (Ljava/lang/String;I)[I */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScreenMode0 - (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorDevice0 + (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx) { DISPLAY_DEVICE device; - LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx); - if(NULL == deviceName) { - DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx); + LPCTSTR adapterName; + { +#ifdef UNICODE + adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName); +#else + adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL); +#endif + } + + HDC hdc = NewtScreen_createDisplayDC(adapterName); + int widthmm = GetDeviceCaps(hdc, HORZSIZE); + int heightmm = GetDeviceCaps(hdc, VERTSIZE); + DeleteDC(hdc); + int devModeID = ENUM_CURRENT_SETTINGS; + + DEVMODE dm; + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, 0); + DBG_PRINT("*** WindowsWindow: getMonitorDevice.EnumDisplaySettingsEx(%s, devModeID %d) -> %d\n", adapterName, devModeID, res); +#ifdef UNICODE + free((void*) adapterName); +#else + (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName); +#endif + if (0 == res) { + return (*env)->NewIntArray(env, 0); + } + + jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES; + jint prop[ propCount ]; + int propIndex = 0; + + prop[propIndex++] = propCount; + prop[propIndex++] = monitor_idx; + prop[propIndex++] = widthmm; + prop[propIndex++] = heightmm; + prop[propIndex++] = dm.dmPosition.x; // rotated viewport + prop[propIndex++] = dm.dmPosition.y; // rotated viewport + prop[propIndex++] = dm.dmPelsWidth; // rotated viewport + prop[propIndex++] = dm.dmPelsHeight; // rotated viewport + + jintArray properties = (*env)->NewIntArray(env, propCount); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount); + } + (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop); + + return properties; +} + +/* + * Class: jogamp_newt_driver_windows_ScreenDriver + * Method: setMonitorMode0 + * Signature: (IIIIIIIII)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setMonitorMode0 + (JNIEnv *env, jobject object, jint monitor_idx, jint x, jint y, jint width, jint height, jint bits, jint rate, jint flags, jint rot) +{ + DISPLAY_DEVICE adapterDevice, monitorDevice; + LPCTSTR adapterName = NewtScreen_getAdapterName(&adapterDevice, monitor_idx); + if(NULL == adapterName) { + DBG_PRINT("*** WindowsWindow: setMonitorMode.getAdapterName(monitor_idx %d) -> NULL\n", monitor_idx); + return JNI_FALSE; + } + LPCTSTR monitorName = NewtScreen_getMonitorName(adapterName, &monitorDevice, 0, TRUE); + if(NULL == monitorName) { + DBG_PRINT("*** WindowsWindow: setMonitorMode.getMonitorName(monitor_idx 0) -> NULL\n"); return JNI_FALSE; } @@ -1339,10 +1488,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree // initialize the DEVMODE structure ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); + if( 0 <= x && 0 <= y ) { + dm.dmPosition.x = (int)x; + dm.dmPosition.y = (int)y; + } dm.dmPelsWidth = (int)width; dm.dmPelsHeight = (int)height; dm.dmBitsPerPel = (int)bits; dm.dmDisplayFrequency = (int)rate; + if( 0 != ( flags & FLAG_INTERLACE ) ) { + dm.dmDisplayFlags |= DM_INTERLACED; + } dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot); // swap width and height, since Windows reflects rotated dimension, we don't @@ -1352,9 +1508,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree dm.dmPelsHeight = tempWidth; } - dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; + dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; + if( 0 <= x && 0 <= y ) { + dm.dmFields |= DM_POSITION; + } - return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ; + return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(adapterName, &dm, NULL, 0, NULL) ) ? JNI_TRUE : JNI_FALSE ; } /* diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c index cbf911a38..81a6726b5 100644 --- a/src/newt/native/X11RandR11.c +++ b/src/newt/native/X11RandR11.c @@ -30,10 +30,10 @@ /* * Class: jogamp_newt_driver_x11_RandR11 - * Method: getAvailableScreenModeRotations0 + * Method: getAvailableScreenRotations0 * Signature: (JI)I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenModeRotations0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenRotations0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -75,10 +75,10 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScre /* * Class: jogamp_newt_driver_x11_RandR11 - * Method: getNumScreenModeResolution0 + * Method: getNumScreenResolution0 * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenModeResolutions0 +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenResolutions0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -90,7 +90,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenModeResol #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "X11Screen_getNumScreenModeResolution0.1: %ld ms\n", td_ms); fflush(NULL); + fprintf(stderr, "X11Screen_getNumScreenResolution0.1: %ld ms\n", td_ms); fflush(NULL); #endif int num_sizes; @@ -98,20 +98,20 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenModeResol #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "X11Screen_getNumScreenModeResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL); + fprintf(stderr, "X11Screen_getNumScreenResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL); #endif - DBG_PRINT("getNumScreenModeResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes); + DBG_PRINT("getNumScreenResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes); return num_sizes; } /* * Class: jogamp_newt_driver_x11_RandR11 - * Method: getScreenModeResolutions0 + * Method: getScreenResolutions0 * Signature: (JII)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenModeResolution0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenResolution0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -145,10 +145,10 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenModeRes /* * Class: jogamp_newt_driver_x11_RandR11 - * Method: getScreenModeRates0 + * Method: getScreenRates0 * Signature: (JII)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenModeRates0 +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenRates0 (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) { Display *dpy = (Display *) (intptr_t) display; @@ -289,36 +289,20 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenM int num_sizes; XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - int rot; if( 0 > resMode_idx || resMode_idx >= num_sizes ) { NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); } - switch(rotation) { - case 0: - rot = RR_Rotate_0; - break; - case 90: - rot = RR_Rotate_90; - break; - case 180: - rot = RR_Rotate_180; - break; - case 270: - rot = RR_Rotate_270; - break; - default: - NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation); - } - DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); + int xrot = NewtScreen_Degree2XRotation(env, rotation); + XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); XSync(dpy, False); - XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); + XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime); XSync(dpy, False); return JNI_TRUE; diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c index ea72cd35d..92c20e893 100644 --- a/src/newt/native/X11RandR13.c +++ b/src/newt/native/X11RandR13.c @@ -38,22 +38,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0 { Display *dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); -#ifdef DBG_PERF - struct timespec t0, t1, td; - long td_ms; - timespec_now(&t0); -#endif - -#ifdef DBG_PERF - timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "X11Screen_getScreenResources0.1: %ld ms\n", td_ms); fflush(NULL); -#endif - - XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); -#ifdef DBG_PERF - timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); - fprintf(stderr, "X11Screen_getScreenResources0.2 (XRRScreenResources): %ld ms\n", td_ms); fflush(NULL); -#endif + + XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3 + // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2 return (jlong) (intptr_t) res; } @@ -66,48 +53,166 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0 (JNIEnv *env, jclass clazz, jlong screenResources) { - XRRFreeScreenResources( (XRRScreenResources *) (intptr_t) screenResources ); + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + if( NULL != resources ) { + XRRFreeScreenResources( resources ); + } +} + +#define SAFE_STRING(s) (NULL==s?"":s) + +static void dumpOutputs(const char *prefix, Display *dpy, XRRScreenResources *resources, int noutput, RROutput * outputs) { + int i, j; + fprintf(stderr, "%s %p: Output count %d\n", prefix, resources, noutput); + for(i=0; icrtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, xrrOutputInfo->mm_width, xrrOutputInfo->mm_height, + xrrOutputInfo->ncrtc, xrrOutputInfo->nmode, xrrOutputInfo->npreferred); + for(j=0; jnmode; j++) { + fprintf(stderr, " Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]); + } + XRRFreeOutputInfo (xrrOutputInfo); + } } -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getOrigin0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +/** Returns vertical refresh rate in hertz */ +static float getVRefresh(XRRModeInfo *mode) { + float rate; + unsigned int vTotal = mode->vTotal; + + if (mode->modeFlags & RR_DoubleScan) { + /* doublescan doubles the number of lines */ + vTotal *= 2; + } + + if (mode->modeFlags & RR_Interlace) { + /* interlace splits the frame into two fields */ + /* the field rate is what is typically reported by monitors */ + vTotal /= 2; + } + + if (mode->hTotal && vTotal) { + rate = ( (float) mode->dotClock / + ( (float) mode->hTotal * (float) vTotal ) + ); + } else { + rate = 0; + } + return rate; +} + + +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources) { Display * dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); + Window root = RootWindow(dpy, (int)screen_idx); + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; int pos[] = { 0, 0 } ; + int i, j, minWidth, minHeight, maxWidth, maxHeight; - int i; - XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root); - fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc); - for(i=0; incrtc; i++) { - RRCrtc crtc = xrrScreenResources->crtcs[i]; - XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc); - fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height); + int vs_width = DisplayWidth(dpy, screen_idx); + int vs_height = DisplayHeight(dpy, screen_idx); + int vs_width_mm = DisplayWidthMM(dpy, screen_idx); + int vs_height_mm = DisplayHeightMM(dpy, screen_idx); + fprintf(stderr, "ScreenVirtualSize: %dx%d %dx%d mm\n", vs_width, vs_height, vs_width_mm, vs_height_mm); + + XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight); + fprintf(stderr, "XRRGetScreenSizeRange: %dx%d .. %dx%d\n", minWidth, minHeight, maxWidth, maxHeight); + + if( NULL == resources ) { + fprintf(stderr, "XRRScreenResources NULL\n"); + return; + } + fprintf(stderr, "XRRScreenResources %p: Crtc count %d\n", resources, resources->ncrtc); + for(i=0; incrtc; i++) { + RRCrtc crtc = resources->crtcs[i]; + XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc); + fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n", + i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode); + for(j=0; jnoutput; j++) { + fprintf(stderr, " Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]); + } XRRFreeCrtcInfo(xrrCrtcInfo); } - jintArray jpos = (*env)->NewIntArray(env, num_rotations); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 2); + dumpOutputs("XRRScreenResources.outputs", dpy, resources, resources->noutput, resources->outputs); + + fprintf(stderr, "XRRScreenResources %p: Mode count %d\n", resources, resources->nmode); + for(i=0; inmode; i++) { + XRRModeInfo *mode = &resources->modes[i]; + + unsigned int dots = mode->hTotal * mode->vTotal; + float refresh = getVRefresh(mode); + fprintf(stderr, "Mode[%d, id %#lx]: %ux%u@%f, name %s\n", i, mode->id, mode->width, mode->height, refresh, SAFE_STRING(mode->name)); } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, jpos, 0, 2, pos); - return jpos; } -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableScreenModeRotations0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +/* + * Class: jogamp_newt_driver_x11_RandR13 + * Method: getMonitorDeviceCount0 + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0 + (JNIEnv *env, jclass clazz, jlong screenResources) +{ + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + return ( NULL != resources ) ? resources->ncrtc : 0; +} + +/* + * Class: jogamp_newt_driver_x11_RandR13 + * Method: getMonitorInfoHandle0 + * Signature: (JIJI)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx) { Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - int num_rotations = 0; - Rotation cur_rotation, rotations_supported; - int rotations[4]; - int major, minor; + Window root = RootWindow(dpy, (int)screen_idx); + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; - rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation); + if( NULL == resources || crt_idx >= resources->ncrtc ) { + return 0; + } + RRCrtc crtc = resources->crtcs[crt_idx]; + XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc); + return (jlong) (intptr_t) xrrCrtcInfo; +} + +/* + * Class: jogamp_newt_driver_x11_RandR13 + * Method: freeMonitorInfoHandle0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeMonitorInfoHandle0 + (JNIEnv *env, jclass clazz, jlong monitorInfo) +{ + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; + if( NULL != xrrCrtcInfo ) { + XRRFreeCrtcInfo( xrrCrtcInfo ); + } +} + +/* + * Class: jogamp_newt_driver_x11_RandR13 + * Method: getAvailableRotations0 + * Signature: (J)I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableRotations0 + (JNIEnv *env, jclass clazz, jlong monitorInfo) +{ + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; + if( NULL == xrrCrtcInfo ) { + return NULL; + } + Rotation rotations_supported = xrrCrtcInfo->rotations; + + int num_rotations = 0; + int rotations[4]; if(0 != (rotations_supported & RR_Rotate_0)) { rotations[num_rotations++] = 0; } @@ -120,7 +225,7 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableScre if(0 != (rotations_supported & RR_Rotate_270)) { rotations[num_rotations++] = 270; } - + jintArray properties = NULL; if(num_rotations>0) { @@ -136,273 +241,275 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableScre return properties; } -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getNumScreenModeResolutions0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +/* + * Class: jogamp_newt_driver_x11_RandR13 + * Method: getMonitorViewport0 + * Signature: (J)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorViewport0 + (JNIEnv *env, jclass clazz, jlong monitorInfo) { - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes); + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; - int i; - XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root); - fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc); - for(i=0; incrtc; i++) { - RRCrtc crtc = xrrScreenResources->crtcs[i]; - XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc); - fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height); - XRRFreeCrtcInfo(xrrCrtcInfo); + if( NULL == xrrCrtcInfo ) { + // n/a + return NULL; } - fprintf(stderr, "XRRScreenResources %p: XRRModeInfo modes %d\n", xrrScreenResources, xrrScreenResources->nmode); - for(i=0; inmode; i++) { - XRRModeInfo xrrModeInfo = xrrScreenResources->modes[i]; - fprintf(stderr, "XRRModeInfo %d: %dx%d, %s, %X\n", i, xrrModeInfo.width, xrrModeInfo.height, xrrModeInfo.name, xrrModeInfo.id); + + if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) { + // disabled + return NULL; } - XRRFreeScreenResources(xrrScreenResources); - return num_sizes; + jsize propCount = 4; + jint prop[ propCount ]; + int propIndex = 0; + + prop[propIndex++] = xrrCrtcInfo->x; + prop[propIndex++] = xrrCrtcInfo->y; + prop[propIndex++] = xrrCrtcInfo->width; + prop[propIndex++] = xrrCrtcInfo->height; + + jintArray properties = (*env)->NewIntArray(env, propCount); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount); + } + (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop); + + return properties; } /* * Class: jogamp_newt_driver_x11_RandR13 - * Method: getScreenModeResolutions0 - * Signature: (JII)[I + * Method: getMonitorMode0 + * Signature: (JI)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenModeResolution0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorMode0 + (JNIEnv *env, jclass clazz, jlong screenResources, jint mode_idx) { - Display *dpy = (Display *) (intptr_t) display; - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + + if( NULL == resources || mode_idx >= resources->nmode ) { + return NULL; + } - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + XRRModeInfo *mode = &resources->modes[mode_idx]; + unsigned int dots = mode->hTotal * mode->vTotal; + int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100 + int flags = 0; + if (mode->modeFlags & RR_Interlace) { + flags |= FLAG_INTERLACE; } - - // Fill the properties in temp jint array + if (mode->modeFlags & RR_DoubleScan) { + flags |= FLAG_DOUBLESCAN; + } + + jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ]; int propIndex = 0; - jint prop[4]; - - prop[propIndex++] = xrrs[(int)resMode_idx].width; - prop[propIndex++] = xrrs[(int)resMode_idx].height; - prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; - prop[propIndex++] = xrrs[(int)resMode_idx].mheight; - - jintArray properties = (*env)->NewIntArray(env, 4); + + prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL; + prop[propIndex++] = mode->width; + prop[propIndex++] = mode->height; + prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp + prop[propIndex++] = refresh; + prop[propIndex++] = flags; + prop[propIndex++] = mode->id; + prop[propIndex++] = -1; // rotation placeholder + + jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL); if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4); + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL); } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, 4, prop); + (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop); return properties; } /* * Class: jogamp_newt_driver_x11_RandR13 - * Method: getScreenModeRates0 - * Signature: (JII)[I + * Method: getMonitorCurrentMode0 + * Signature: (JJ)[I */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenModeRates0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurrentMode0 + (JNIEnv *env, jclass clazz, jlong screenResources, jlong monitorInfo) { - Display *dpy = (Display *) (intptr_t) display; - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + if( NULL == resources || NULL == xrrCrtcInfo ) { + // n/a + return NULL; } - - int num_rates; - short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates); - - jint prop[num_rates]; + + if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) { + // disabled + return NULL; + } + + int modeId = xrrCrtcInfo->mode; + XRRModeInfo *mode = NULL; int i; - for(i=0; inmode; i++) { + XRRModeInfo *imode = &resources->modes[i]; + if( imode->id == modeId ) { + mode = imode; + break; + } } - - jintArray properties = (*env)->NewIntArray(env, num_rates); + if( NULL == mode ) { + // oops .. + return NULL; + } + + unsigned int dots = mode->hTotal * mode->vTotal; + int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100 + int flags = 0; + if (mode->modeFlags & RR_Interlace) { + flags |= FLAG_INTERLACE; + } + if (mode->modeFlags & RR_DoubleScan) { + flags |= FLAG_DOUBLESCAN; + } + + jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ]; + int propIndex = 0; + + prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL; + prop[propIndex++] = mode->width; + prop[propIndex++] = mode->height; + prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp + prop[propIndex++] = refresh; + prop[propIndex++] = flags; + prop[propIndex++] = mode->id; + prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation); + + jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL); if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates); + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL); } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop); + (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop); return properties; } /* * Class: jogamp_newt_driver_x11_RandR13 - * Method: getCurrentScreenRate0 - * Signature: (JI)I + * Method: getMonitorDevice0 + * Signature: (JJJJ)[I */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getCurrentScreenRate0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0 + (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx) { - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - // get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); + Display * dpy = (Display *) (intptr_t) display; + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate); + if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) { + // n/a + return NULL; + } - return (jint) original_rate; -} + if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) { + // disabled + return NULL; + } -/* - * Class: jogamp_newt_driver_x11_RandR13 - * Method: getCurrentScreenRotation0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getCurrentScreenRotation0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - //get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - - Rotation rotation; - XRRConfigCurrentConfiguration(conf, &rotation); + RROutput output = xrrCrtcInfo->outputs[0]; + XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output); + int numModes = xrrOutputInfo->nmode; - //free - XRRFreeScreenConfigInfo(conf); - - return NewtScreen_XRotation2Degree(env, rotation); -} + jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes; + jint prop[ propCount ]; + int propIndex = 0; + prop[propIndex++] = propCount; + prop[propIndex++] = crt_idx; + prop[propIndex++] = xrrOutputInfo->mm_width; + prop[propIndex++] = xrrOutputInfo->mm_height; + prop[propIndex++] = xrrCrtcInfo->x; + prop[propIndex++] = xrrCrtcInfo->y; + prop[propIndex++] = xrrCrtcInfo->width; + prop[propIndex++] = xrrCrtcInfo->height; + prop[propIndex++] = xrrCrtcInfo->mode; // current mode id + prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation); + int i; + for(i=0; imodes[i]; + } -/* - * Class: jogamp_newt_driver_x11_RandR13 - * Method: getCurrentScreenResolutionIndex0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getCurrentScreenResolutionIndex0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - // get current resolutions and frequency configuration - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); - - Rotation original_rotation; - SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); - - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id); - return (jint)original_size_id; + XRRFreeOutputInfo (xrrOutputInfo); + + jintArray properties = (*env)->NewIntArray(env, propCount); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount); + } + (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop); + + return properties; } /* * Class: jogamp_newt_driver_x11_RandR13 - * Method: setCurrentScreenModeStart0 - * Signature: (JIIII)Z + * Method: setMonitorMode0 + * Signature: (JJJIIIII)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setCurrentScreenModeStart0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0 + (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y) { - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)screen_idx); + Display * dpy = (Display *) (intptr_t) display; + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; + jboolean res = JNI_FALSE; - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - int rot; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) { + // n/a + return res; } - conf = XRRGetScreenInfo(dpy, root); - - rot = int NewtScreen_Degree2XRotation(env, rotation); - - DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", - resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); + if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) { + // disabled + return res; + } - XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); + if( 0 >= modeId ) { + // oops .. + return res; + } - XSync(dpy, False); - XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); - XSync(dpy, False); + if( 0 > x || 0 > y ) { + x = xrrCrtcInfo->x; + y = xrrCrtcInfo->y; + } - //free - XRRFreeScreenConfigInfo(conf); - XSync(dpy, False); + Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime, + x, y, modeId, NewtScreen_Degree2XRotation(env, rotation), + xrrCrtcInfo->outputs, xrrCrtcInfo->noutput ); + res = status == RRSetConfigSuccess; - return JNI_TRUE; + return res; } /* * Class: jogamp_newt_driver_x11_RandR13 - * Method: setCurrentScreenModePollEnd0 - * Signature: (J)Z + * Method: setScreenViewport0 + * Signature: (JIJIIII)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setCurrentScreenModePollEnd0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint x, jint y, jint width, jint height) { - Display *dpy = (Display *) (intptr_t) display; - int randr_event_base, randr_error_base; - XEvent evt; - XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; + Display * dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)screen_idx); + XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; + jboolean res = JNI_FALSE; - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + if( NULL == resources ) { + // n/a + return JNI_FALSE; } - XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); - - int done = 0; - int rot; - do { - if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { - return; - } - XNextEvent(dpy, &evt); - - switch (evt.type - randr_event_base) { - case RRScreenChangeNotify: - rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation); - DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", - (void*)scn_event->window, (void*)scn_event->root, - (int)scn_event->size_index, rot, - scn_event->width, scn_event->height); - // done = scn_event->size_index == resMode_idx; // not reliable .. - done = rot == rotation && - scn_event->width == xrrs[resMode_idx].width && - scn_event->height == xrrs[resMode_idx].height; - break; - default: - DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window); - } - XRRUpdateConfiguration(&evt); - } while(!done); - - XSync(dpy, False); - + XRRSetScreenSize (dpy, root, width, height, DisplayWidthMM(dpy, screen_idx), DisplayHeightMM(dpy, screen_idx)); + return JNI_TRUE; } + diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c index 3d4b2a26c..152a092c9 100644 --- a/src/newt/native/X11Screen.c +++ b/src/newt/native/X11Screen.c @@ -75,22 +75,41 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0 } int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { - int rot; + int degree; if(xrotation == RR_Rotate_0) { - rot = 0; + degree = 0; } else if(xrotation == RR_Rotate_90) { - rot = 90; + degree = 90; } else if(xrotation == RR_Rotate_180) { - rot = 180; + degree = 180; } else if(xrotation == RR_Rotate_270) { - rot = 270; + degree = 270; } else { NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation); } - return rot; + return degree; +} + +int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) { + int xrot; + if(degree == 0) { + xrot = RR_Rotate_0; + } + else if(degree == 90) { + xrot = RR_Rotate_90; + } + else if(degree == 180) { + xrot = RR_Rotate_180; + } + else if(degree == 270) { + xrot = RR_Rotate_270; + } else { + NewtCommon_throwNewRuntimeException(env, "invalid degree: %d", degree); + } + return xrot; } /* diff --git a/src/newt/native/X11Screen.h b/src/newt/native/X11Screen.h index 1a1440054..c81ee05d5 100644 --- a/src/newt/native/X11Screen.h +++ b/src/newt/native/X11Screen.h @@ -33,5 +33,6 @@ #include "X11Common.h" int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation); +int NewtScreen_Degree2XRotation(JNIEnv *env, int degree); #endif /* _X11SCREEN_H */ diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 9e96169f5..6c5a127b6 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -438,7 +438,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind return 0; // Error } -static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) { +static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) { XWindowAttributes xwa; Window focus_return; int revert_to_return; @@ -447,7 +447,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, XGetInputFocus(dpy, &focus_return, &revert_to_return); DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w); - if( JNI_TRUE==force || focus_return!=w) { + if( True==force || focus_return!=w) { DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); XRaiseWindow(dpy, w); NewtWindows_setCWAbove(dpy, w); @@ -743,7 +743,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ; int fsEWMHFlags = 0; if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) { - fsEWMHFlags |= _NET_WM_FULLSCREEN; + if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors + fsEWMHFlags |= _NET_WM_FULLSCREEN; + } if( TST_FLAG_IS_FULLSCREEN(flags) ) { if( TST_FLAG_IS_ALWAYSONTOP(flags) ) { fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on @@ -756,12 +758,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo fsEWMHFlags |= _NET_WM_ABOVE; // toggle above } - DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", + DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w, x, y, width, height, TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags), TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags), - TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), + TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags), TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHFlags); @@ -769,9 +771,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo // However, we have to consider other cases like reparenting and WM which don't support it. if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible && + !TST_FLAG_IS_FULLSCREEN_SPAN(flags) && ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) { Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ; if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { + if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration + NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True); + } #ifdef FS_GRAB_KEYBOARD if(TST_FLAG_CHANGE_FULLSCREEN(flags)) { if(TST_FLAG_IS_FULLSCREEN(flags)) { @@ -866,7 +872,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0 (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force) { - NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ; + NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ; } /* diff --git a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java index 0dead125a..88cd9a719 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.ElektronenMultiplizierer; @@ -58,11 +58,13 @@ public class NEWTElektronActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new ElektronenMultiplizierer()); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java index c020413cf..f10cfc11f 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; @@ -63,11 +63,13 @@ public class NEWTGearsES1Activity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GearsES1(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java index 542912c08..2e9774565 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java @@ -36,10 +36,10 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.event.MonitorEvent; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -75,11 +75,13 @@ public class NEWTGearsES2Activity extends NewtBaseActivity { GearsES2 demo = new GearsES2(-1); // demo.enableAndroidTrace(true); glWindow.addGLEventListener(demo); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); if( null != System.getProperty(forceKillProcessTest) ) { Log.d(TAG, "forceKillProcessTest"); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java index 5e7a5c489..c87e66189 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java @@ -57,6 +57,7 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Screen", "true"); props.setProperty("newt.debug.Window", "true"); props.setProperty("newt.debug.Window.MouseEvent", "true"); props.setProperty("newt.debug.Window.KeyEvent", "true"); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java index 18c3cb042..98e6b7c5f 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java @@ -34,8 +34,8 @@ import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -65,11 +65,13 @@ public class NEWTGearsES2TransActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GearsES2(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); Animator animator = new Animator(glWindow); // glWindow.setSkipContextReleaseThread(animator.getThread()); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java index bbd4f9f20..42db9d8dd 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A; @@ -61,11 +61,13 @@ public class NEWTGraphUI1pActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GPUUISceneGLListener0A(0)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java index 20ba3f484..c68de95cc 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java @@ -33,8 +33,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.graph.curve.Region; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A; @@ -62,11 +62,13 @@ public class NEWTGraphUI2pActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GPUUISceneGLListener0A(Region.VBAA_RENDERING_BIT)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java index 06ce75ac5..08fbf643d 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; @@ -57,11 +57,13 @@ public class NEWTRedSquareES1Activity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new RedSquareES1(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java index 02e2d8f01..cefdd842b 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; @@ -62,11 +62,13 @@ public class NEWTRedSquareES2Activity extends NewtBaseActivity { final RedSquareES2 demo = new RedSquareES2(-1); // demo.enableAndroidTrace(true); glWindow.addGLEventListener(demo); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); Animator animator = new Animator(glWindow); // animator.setRunAsFastAsPossible(true); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index 50f759079..4c6cae501 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -163,13 +163,25 @@ public class TestGearsES2NEWT extends UITestCase { }); glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); - glWindow.setFullscreen(!glWindow.isFullscreen()); + if( glWindow.isFullscreen() ) { + glWindow.setFullscreen( false ); + } else { + if( e.isAltDown() ) { + glWindow.setFullscreen( null ); + } else { + glWindow.setFullscreen( true ); + } + } System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java index 98620e0c1..90d4a9c1f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java @@ -28,8 +28,8 @@ package com.jogamp.opengl.test.junit.jogl.glsl; import com.jogamp.common.nio.Buffers; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.MonitorMode; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -109,11 +109,13 @@ public class TestRulerNEWT01 extends UITestCase { Assert.assertNotNull(winctx); Assert.assertNotNull(winctx.window); Assert.assertNotNull(winctx.window.getScreen()); - ScreenMode sm = winctx.window.getScreen().getCurrentScreenMode(); - Assert.assertNotNull(sm); - System.err.println(sm); - final MonitorMode mmode = sm.getMonitorMode(); - final DimensionImmutable sdim = mmode.getScreenSizeMM(); + final MonitorDevice monitor = winctx.window.getMainMonitor(); + Assert.assertNotNull(monitor); + System.err.println(monitor); + final MonitorMode mmode = monitor.getCurrentMode(); + Assert.assertNotNull(mmode); + System.err.println(mmode); + final DimensionImmutable sdim = monitor.getSizeMM(); final DimensionImmutable spix = mmode.getSurfaceSize().getResolution(); final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2)); final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer(); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java index 29ec443f7..a7b65545a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java @@ -35,11 +35,12 @@ import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.Animator; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; @@ -72,8 +73,8 @@ public class ManualScreenMode03NEWT extends UITestCase { Screen screen = NewtFactory.createScreen(display, 0); // screen 0 GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); - List screenModes = screen.getScreenModes(); - if(null==screenModes) { + List monitorModes = screen.getMonitorModes(); + if(null==monitorModes) { // no support .. System.err.println("Your platform has no ScreenMode change support, sorry"); return; @@ -81,18 +82,21 @@ public class ManualScreenMode03NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); - ScreenMode smCurrent = screen.getCurrentScreenMode(); - ScreenMode smOrig = screen.getOriginalScreenMode(); - System.err.println("[0] current/orig: "+smCurrent); + MonitorDevice monitor = window.getMainMonitor(); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + MonitorMode mmOrig = monitor.getOriginalMode(); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); - ScreenMode sm = (ScreenMode) screenModes.get(0); - System.err.println("[0] set current: "+sm); - screen.setCurrentScreenMode(sm); + MonitorMode mm = (MonitorMode) monitorModes.get(0); + System.err.println("[0] set current: "+mm); + monitor.setCurrentMode(mm); System.err.print("[0] post setting .. wait <"); try { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java index 577119bcd..f64cf2eb8 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java @@ -35,18 +35,23 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import com.jogamp.common.util.ArrayHashSet; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.MonitorMode; -import com.jogamp.newt.util.ScreenModeUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.Iterator; import java.util.List; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.SurfaceSize; +import javax.media.opengl.GLProfile; + +import jogamp.newt.MonitorDeviceImpl; +import jogamp.newt.MonitorModeProps; public class TestScreenMode00NEWT extends UITestCase { static int screenIdx = 0; @@ -59,6 +64,7 @@ public class TestScreenMode00NEWT extends UITestCase { @BeforeClass public static void initClass() { + GLProfile.initSingleton(); // hack to initialize GL for BCM_IV (Rasp.Pi) NativeWindowFactory.initSingleton(); width = 640; height = 480; @@ -66,31 +72,46 @@ public class TestScreenMode00NEWT extends UITestCase { @Test public void testScreenModeInfo00() throws InterruptedException { - DimensionImmutable res = new Dimension(640, 480); - SurfaceSize surfsz = new SurfaceSize(res, 32); - DimensionImmutable mm = new Dimension(500, 400); - MonitorMode mon = new MonitorMode(surfsz, mm, 60); - ScreenMode sm_out = new ScreenMode(mon, 90); - System.err.println("00 out: "+sm_out); - - int[] props = ScreenModeUtil.streamOut(sm_out); - ScreenMode sm_in = ScreenModeUtil.streamIn(props, 0); - System.err.println("00 in : "+sm_in); - - Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize().getResolution(), - sm_out.getMonitorMode().getSurfaceSize().getResolution()); - - Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize(), - sm_out.getMonitorMode().getSurfaceSize()); - - Assert.assertEquals(sm_in.getMonitorMode().getScreenSizeMM(), - sm_out.getMonitorMode().getScreenSizeMM()); - - Assert.assertEquals(sm_in.getMonitorMode(), sm_out.getMonitorMode()); - - Assert.assertEquals(sm_in, sm_out); + final DimensionImmutable res = new Dimension(640, 480); + final SurfaceSize surfsz = new SurfaceSize(res, 32); + final MonitorMode modeOut = new MonitorMode(surfsz, 60.0f, 0, 0); + System.err.println("00 out: "+modeOut); + final MonitorModeProps.Cache cache = new MonitorModeProps.Cache(); + cache.monitorModes.add(modeOut); + { + final int[] props = MonitorModeProps.streamOutMonitorMode(modeOut); + final MonitorMode modeIn = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + System.err.println("00 in : "+modeIn); + + Assert.assertEquals(modeOut.getSurfaceSize().getResolution(), modeIn.getSurfaceSize().getResolution()); + + Assert.assertEquals(modeOut.getSurfaceSize(), modeIn.getSurfaceSize()); + + Assert.assertEquals(modeOut.hashCode(), modeIn.hashCode()); + + Assert.assertEquals(modeOut, modeIn); + } - Assert.assertEquals(sm_out.hashCode(), sm_in.hashCode()); + final DimensionImmutable sizeMM = new Dimension(50, 50); + final Rectangle viewport = new Rectangle(0, 0, 1920, 1080); + final ArrayHashSet supportedModes = new ArrayHashSet(); + supportedModes.add(modeOut); + final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, viewport, modeOut, supportedModes); + System.err.println("01 out : "+monOut); + cache.monitorDevices.add(monOut); + { + final int[] props = MonitorModeProps.streamOutMonitorDevice(monOut); + final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(null, cache, null, props, 0); + System.err.println("01 in : "+monIn); + + Assert.assertEquals(monOut.getCurrentMode(), monOut.getOriginalMode()); + Assert.assertEquals(monOut.getSupportedModes(), monIn.getSupportedModes()); + Assert.assertEquals(monOut.getViewport(), monIn.getViewport()); + Assert.assertEquals(monOut.getOriginalMode(), monIn.getOriginalMode()); + Assert.assertEquals(monOut.getCurrentMode(), monIn.getCurrentMode()); + Assert.assertEquals(monOut.hashCode(), monIn.hashCode()); + Assert.assertEquals(monOut, monIn); + } } @Test @@ -101,21 +122,37 @@ public class TestScreenMode00NEWT extends UITestCase { Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,screen.getDisplay().isNativeValid()); System.err.println("Screen: "+screen.toString()); - - List screenModes = screen.getScreenModes(); - Assert.assertTrue(screenModes.size()>0); - int i=0; - for(Iterator iter=screenModes.iterator(); iter.hasNext(); i++) { - System.err.println(i+": "+iter.next()); + List allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + { + int i=0; + for(Iterator iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) { + System.err.println("All["+i+"]: "+iMode.next()); + } + } + + List monitors = screen.getMonitorDevices(); + Assert.assertTrue(monitors.size()>0); + int j=0; + for(Iterator iMonitor=monitors.iterator(); iMonitor.hasNext(); j++) { + MonitorDevice monitor = iMonitor.next(); + System.err.println(j+": "+monitor); + List modes = monitor.getSupportedModes(); + Assert.assertTrue(modes.size()>0); + int i=0; + for(Iterator iMode=modes.iterator(); iMode.hasNext(); i++) { + System.err.println("["+j+"]["+i+"]: "+iMode.next()); + } + Assert.assertTrue(allMonitorModes.containsAll(modes)); + + MonitorMode sm_o = monitor.getOriginalMode(); + Assert.assertNotNull(sm_o); + MonitorMode sm_c = monitor.queryCurrentMode(); + System.err.println("[0] orig : "+sm_o); + System.err.println("[0] current: "+sm_c); + Assert.assertNotNull(sm_c); + Assert.assertEquals(sm_o, sm_c); } - ScreenMode sm_o = screen.getOriginalScreenMode(); - Assert.assertNotNull(sm_o); - ScreenMode sm_c = screen.getCurrentScreenMode(); - Assert.assertNotNull(sm_c); - System.err.println("orig SM: "+sm_o); - System.err.println("curr SM: "+sm_c); - System.err.println("curr sz: "+screen.getWidth()+"x"+screen.getHeight()); - Assert.assertEquals(sm_o, sm_c); screen.removeReference(); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java index 75a312686..f4eaec5fa 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java @@ -36,9 +36,10 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -81,23 +82,24 @@ public class TestScreenMode00bNEWT extends UITestCase { Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,display.isNativeValid()); - List screenModes = screen.getScreenModes(); + List screenModes = screen.getMonitorModes(); Assert.assertTrue(screenModes.size()>0); int i=0; - for(Iterator iter=screenModes.iterator(); iter.hasNext(); i++) { + for(Iterator iter=screenModes.iterator(); iter.hasNext(); i++) { System.err.println(i+": "+iter.next()); } - ScreenMode sm_o = screen.getOriginalScreenMode(); + MonitorDevice monitor = window.getMainMonitor(); + MonitorMode mm_o = monitor.getOriginalMode(); - Assert.assertNotNull(sm_o); - ScreenMode sm_c = screen.getCurrentScreenMode(); - Assert.assertNotNull(sm_c); - System.err.println("orig: "+sm_o); - System.err.println("curr: "+sm_c); + Assert.assertNotNull(mm_o); + MonitorMode mm_c = monitor.queryCurrentMode(); + Assert.assertNotNull(mm_c); + System.err.println("orig: "+mm_o); + System.err.println("curr: "+mm_c); for(i=0; i<50; i++) { - sm_c = screen.getCurrentScreenMode(); - Assert.assertNotNull(sm_c); + mm_c = monitor.queryCurrentMode(); + Assert.assertNotNull(mm_c); System.err.print("."+i); } System.err.println("!"); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java index f253f3b58..78dd9fbc1 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java @@ -40,12 +40,13 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -149,14 +150,16 @@ public class TestScreenMode01NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); + final MonitorDevice monitor = window.getMainMonitor(); + Assert.assertEquals(false, window.isFullscreen()); Assert.assertEquals(width, window.getWidth()); Assert.assertEquals(height, window.getHeight()); window.setFullscreen(true); - Assert.assertEquals(true, window.isFullscreen()); - Assert.assertEquals(window.getScreen().getWidth(), window.getWidth()); - Assert.assertEquals(window.getScreen().getHeight(), window.getHeight()); + Assert.assertEquals(true, window.isFullscreen()); + Assert.assertEquals(monitor.getViewport().getWidth(), window.getWidth()); + Assert.assertEquals(monitor.getViewport().getHeight(), window.getHeight()); Thread.sleep(waitTimeShort); @@ -192,45 +195,53 @@ public class TestScreenMode01NEWT extends UITestCase { GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); Assert.assertNotNull(window); - List screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + MonitorDevice monitor = window.getMainMonitor(); + + List monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { // no support .. - System.err.println("Your platform has no ScreenMode change support, sorry"); + System.err.println("Your platform has no MonitorMode change support, sorry"); destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); Animator animator = new Animator(window); animator.start(); - ScreenMode smCurrent = screen.getCurrentScreenMode(); - Assert.assertNotNull(smCurrent); - ScreenMode smOrig = screen.getOriginalScreenMode(); - Assert.assertNotNull(smOrig); - Assert.assertEquals(smCurrent, smOrig); - System.err.println("[0] current/orig: "+smCurrent); - - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); - ScreenMode sm = (ScreenMode) screenModes.get(0); + MonitorMode sm = (MonitorMode) monitorModes.get(0); System.err.println("[0] set current: "+sm); - screen.setCurrentScreenMode(sm); - Assert.assertEquals(sm, screen.getCurrentScreenMode()); - Assert.assertNotSame(smOrig, screen.getCurrentScreenMode()); - + monitor.setCurrentMode(sm); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(sm, monitor.getCurrentMode()); + Assert.assertNotSame(mmOrig, monitor.getCurrentMode()); + Assert.assertEquals(sm, monitor.queryCurrentMode()); + Thread.sleep(waitTimeLong); // check reset .. @@ -258,15 +269,14 @@ public class TestScreenMode01NEWT extends UITestCase { Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] current/orig: "+mmCurrent); screen.destroy(); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); - + Assert.assertNotNull(mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); cleanupGL(); } @@ -291,27 +301,30 @@ public class TestScreenMode01NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); - ScreenMode smCurrent = screen.getCurrentScreenMode(); - Assert.assertNotNull(smCurrent); - ScreenMode smOrig = screen.getOriginalScreenMode(); - Assert.assertNotNull(smOrig); - Assert.assertEquals(smCurrent, smOrig); - System.err.println("[0] current/orig: "+smCurrent); + MonitorDevice monitor = window.getMainMonitor(); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); - List screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + List monitorModes = monitor.getSupportedModes(); + if(monitorModes.size()==1) { // no support .. destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); - - ScreenMode screenMode = (ScreenMode) screenModes.get(0); - Assert.assertNotNull(screenMode); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + + MonitorMode monitorMode = (MonitorMode) monitorModes.get(0); + Assert.assertNotNull(monitorMode); if(preFS) { System.err.println("[0] set FS pre 0: "+window.isFullscreen()); @@ -321,8 +334,8 @@ public class TestScreenMode01NEWT extends UITestCase { System.err.println("[0] set FS pre X: "+window.isFullscreen()); } - System.err.println("[0] set current: "+screenMode); - screen.setCurrentScreenMode(screenMode); + System.err.println("[0] set current: "+monitorMode); + monitor.setCurrentMode(monitorMode); if(!preFS) { System.err.println("[0] set FS post 0: "+window.isFullscreen()); @@ -358,14 +371,14 @@ public class TestScreenMode01NEWT extends UITestCase { Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] current/orig: "+mmCurrent); screen.destroy(); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); + Assert.assertNotNull(mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); cleanupGL(); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java new file mode 100644 index 000000000..35390636f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java @@ -0,0 +1,212 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.newt; + +import java.io.IOException; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.util.List; +import javax.media.nativewindow.util.Dimension; + +/** + * Documents remedy B) for NV RANDR/GL bug + * + * @see TestScreenMode01NEWT#cleanupGL() + */ +public class TestScreenMode01aNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + static int waitTimeShort = 2000; + static int waitTimeLong = 2000; + + @BeforeClass + public static void initClass() { + width = 100; + height = 100; + glp = GLProfile.getDefault(); + } + + @AfterClass + public static void releaseClass() throws InterruptedException { + Thread.sleep(waitTimeShort); + } + + static Window createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) { + Assert.assertNotNull(caps); + + GLWindow window = GLWindow.create(screen, caps); + // Window window = NewtFactory.createWindow(screen, caps); + window.setTitle(name); + window.setPosition(x, y); + window.setSize(width, height); + window.addGLEventListener(new GearsES2()); + Assert.assertNotNull(window); + window.setVisible(true); + return window; + } + + static void destroyWindow(Window window) { + if(null!=window) { + window.destroy(); + } + } + + @Test + public void testScreenModeChange01() throws InterruptedException { + Thread.sleep(waitTimeShort); + + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height); + Assert.assertNotNull(window0); + + List allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (all), sorry"); + destroyWindow(window0); + return; + } + + MonitorDevice monitor = window0.getMainMonitor(); + + List monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window0); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + MonitorMode sm = (MonitorMode) monitorModes.get(0); + System.err.println("[0] set current: "+sm); + Assert.assertTrue(monitor.setCurrentMode(sm)); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(sm, monitor.getCurrentMode()); + Assert.assertNotSame(mmOrig, monitor.getCurrentMode()); + Assert.assertEquals(sm, monitor.queryCurrentMode()); + + Thread.sleep(waitTimeShort); + + // check manual reset .. + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window0.isNativeValid()); + Assert.assertEquals(true,window0.isVisible()); + + screen.addReference(); // keep it alive ! + Assert.assertTrue(monitor.setCurrentMode(mmOrig)); + Assert.assertFalse(monitor.isModeChangedByUs()); + Assert.assertEquals(mmOrig, monitor.getCurrentMode()); + Assert.assertNotSame(sm, monitor.getCurrentMode()); + Assert.assertEquals(mmOrig, monitor.queryCurrentMode()); + + destroyWindow(window0); + Assert.assertEquals(false,window0.isVisible()); + Assert.assertEquals(false,window0.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); // alive ! + Assert.assertEquals(true,display.isNativeValid()); + + Thread.sleep(waitTimeShort); + + Window window1 = createWindow(screen, caps, "win1", + width+window0.getInsets().getTotalWidth(), 0, + width, height); + Assert.assertNotNull(window1); + Assert.assertEquals(true,window1.isNativeValid()); + Assert.assertEquals(true,window1.isVisible()); + + Thread.sleep(waitTimeShort); + + destroyWindow(window1); + Assert.assertEquals(false,window1.isNativeValid()); + Assert.assertEquals(false,window1.isVisible()); + + screen.removeReference(); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + String tstname = TestScreenMode01aNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java index 38612faa8..7e18f396a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2013 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,7 +29,6 @@ package com.jogamp.opengl.test.junit.newt; import java.io.IOException; -import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; @@ -39,34 +38,36 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; import java.util.List; import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.RectangleImmutable; /** - * Documents remedy B) for NV RANDR/GL bug - * - * @see TestScreenMode01NEWT#cleanupGL() + * Mode change on separate monitors .. */ public class TestScreenMode01bNEWT extends UITestCase { static GLProfile glp; static int width, height; - static int waitTimeShort = 2000; - static int waitTimeLong = 2000; + static long waitTimeShort = 2000; + static long duration = 6000; @BeforeClass public static void initClass() { - width = 100; - height = 100; + width = 200; + height = 200; glp = GLProfile.getDefault(); } @@ -75,7 +76,7 @@ public class TestScreenMode01bNEWT extends UITestCase { Thread.sleep(waitTimeShort); } - static Window createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) { + static GLWindow createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) throws InterruptedException { Assert.assertNotNull(caps); GLWindow window = GLWindow.create(screen, caps); @@ -85,7 +86,9 @@ public class TestScreenMode01bNEWT extends UITestCase { window.setSize(width, height); window.addGLEventListener(new GearsES2()); Assert.assertNotNull(window); + final long t0 = System.currentTimeMillis(); window.setVisible(true); + System.err.println("Time for visible/pos: "+(System.currentTimeMillis()-t0)+" ms"); return window; } @@ -96,93 +99,150 @@ public class TestScreenMode01bNEWT extends UITestCase { } @Test - public void testScreenModeChange01() throws InterruptedException { + public void testScreenModeChangeSingleQ1() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport(); + testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); + } finally { + screen.removeReference(); + } + } + + @Test + public void testScreenModeChangeSingleQ2() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + if( 2 > screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (1): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); + } finally { + screen.removeReference(); + } + } + + void testScreenModeChangeImpl(final Screen screen, int xpos, int ypos) throws InterruptedException { Thread.sleep(waitTimeShort); - GLCapabilities caps = new GLCapabilities(glp); + final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); - Display display = NewtFactory.createDisplay(null); // local display - Assert.assertNotNull(display); - Screen screen = NewtFactory.createScreen(display, 0); // screen 0 - Assert.assertNotNull(screen); - Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height); + final Display display = screen.getDisplay(); + System.err.println("Test.0: Window screen: "+screen); + + System.err.println("Test.0: Window bounds (pre): "+xpos+"/"+ypos+" "+width+"x"+height+" within "+screen.getViewport()); + + GLWindow window0 = createWindow(screen, caps, "win0", xpos, ypos, width, height); Assert.assertNotNull(window0); + System.err.println("Test.0: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); - List screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + final Animator anim = new Animator(window0); + anim.start(); + + List allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { // no support .. - System.err.println("Your platform has no ScreenMode change support, sorry"); + System.err.println("Your platform has no MonitorMode change support (all), sorry"); destroyWindow(window0); return; } - Assert.assertTrue(screenModes.size()>0); - - ScreenMode smCurrent = screen.getCurrentScreenMode(); - Assert.assertNotNull(smCurrent); - ScreenMode smOrig = screen.getOriginalScreenMode(); - Assert.assertNotNull(smOrig); - Assert.assertEquals(smCurrent, smOrig); - System.err.println("[0] current/orig: "+smCurrent); - - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - ScreenMode sm = (ScreenMode) screenModes.get(0); - System.err.println("[0] set current: "+sm); - screen.setCurrentScreenMode(sm); - Assert.assertEquals(sm, screen.getCurrentScreenMode()); - Assert.assertNotSame(smOrig, screen.getCurrentScreenMode()); - - Thread.sleep(waitTimeShort); - - // check reset .. + MonitorDevice monitor = window0.getMainMonitor(); + System.err.println("Test.0: Window monitor: "+monitor); + + List monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window0); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + MonitorMode mmCurrent = monitor.getCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + MonitorMode sm = (MonitorMode) monitorModes.get(0); + System.err.println("[1] set current: "+sm); + Assert.assertTrue(monitor.setCurrentMode(sm)); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] current: "+mmCurrent); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(sm, monitor.getCurrentMode()); + Assert.assertNotSame(mmOrig, monitor.getCurrentMode()); + Assert.assertEquals(sm, monitor.queryCurrentMode()); + + System.err.println("Test.1: Window screen: "+screen); + System.err.println("Test.1: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.1: Window monitor: "+window0.getMainMonitor()); + + Thread.sleep(duration); Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,window0.isNativeValid()); Assert.assertEquals(true,window0.isVisible()); - screen.addReference(); // keep it alive ! - screen.setCurrentScreenMode(smOrig); + Assert.assertTrue(monitor.setCurrentMode(mmOrig)); + Assert.assertFalse(monitor.isModeChangedByUs()); + Assert.assertEquals(mmOrig, monitor.getCurrentMode()); + Assert.assertNotSame(sm, monitor.getCurrentMode()); + Assert.assertEquals(mmOrig, monitor.queryCurrentMode()); + + System.err.println("Test.2: Window screen: "+screen); + System.err.println("Test.2: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.2: Window monitor: "+window0.getMainMonitor()); + Thread.sleep(duration); + anim.stop(); destroyWindow(window0); Assert.assertEquals(false,window0.isVisible()); Assert.assertEquals(false,window0.isNativeValid()); - Assert.assertEquals(true,screen.isNativeValid()); // alive ! Assert.assertEquals(true,display.isNativeValid()); - - Thread.sleep(waitTimeShort); - - Window window1 = createWindow(screen, caps, "win1", - width+window0.getInsets().getTotalWidth(), 0, - width, height); - Assert.assertNotNull(window1); - Assert.assertEquals(true,window1.isNativeValid()); - Assert.assertEquals(true,window1.isVisible()); - - Thread.sleep(waitTimeShort); - - destroyWindow(window1); - Assert.assertEquals(false,window1.isNativeValid()); - Assert.assertEquals(false,window1.isVisible()); - - screen.removeReference(); - Assert.assertEquals(false,screen.isNativeValid()); - Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); } public static void main(String args[]) throws IOException { + for(int i=0; i screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (1): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null); + } finally { + screen.removeReference(); + } + } + + @Test + public void testScreenFullscreenSpanQ1Q2() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + final int crtCount = screen.getMonitorDevices().size(); + if( 2 >= crtCount ) { + System.err.println("Test Disabled (2): Spanning monitor count "+2+" >= screen monitor count: "+screen); + return; + } + final ArrayList monitors = new ArrayList(); + monitors.add(screen.getMonitorDevices().get(0)); // Q1 + monitors.add(screen.getMonitorDevices().get(1)); // Q2 + RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX()+50, monitorVp.getY()+50, true, monitors); + } finally { + screen.removeReference(); + } + } + + @Test + public void testScreenFullscreenSpanALL() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + if( 2 > screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (3): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX()-50, monitorVp.getY()+50, true, null); + } finally { + screen.removeReference(); + } + } + + void testScreenFullscreenImpl(final Screen screen, int xpos, int ypos, boolean spanAcrossMonitors, List monitors) throws InterruptedException { + Thread.sleep(waitTimeShort); + + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final Display display = screen.getDisplay(); + + System.err.println("Test.0: Window screen: "+screen); + + System.err.println("Test.0: Window bounds (pre): "+xpos+"/"+ypos+" "+width+"x"+height+" within "+screen.getViewport()); + + GLWindow window0 = createWindow(screen, caps, "win0", xpos, ypos, width, height); + Assert.assertNotNull(window0); + System.err.println("Test.0: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + + final Animator anim = new Animator(window0); + anim.start(); + + List allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + + MonitorDevice monitor = window0.getMainMonitor(); + System.err.println("Test.0: Window monitor: "+monitor); + if( !spanAcrossMonitors ) { + window0.setFullscreen(true); + } else { + window0.setFullscreen(monitors); + } + + monitor = window0.getMainMonitor(); + System.err.println("Test.1: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.1: Window monitor: "+monitor.getViewport()); + Rectangle window0Rect = new Rectangle(window0.getX(), window0.getY(), window0.getWidth(), window0.getHeight()); + if( !spanAcrossMonitors ) { + Assert.assertEquals(monitor.getViewport(), window0Rect); + } else { + List monitorsUsed = monitors; + if( null == monitorsUsed ) { + monitorsUsed = window0.getScreen().getMonitorDevices(); + } + Rectangle monitorsUsedViewport = MonitorDevice.unionOfViewports(new Rectangle(), monitorsUsed); + Assert.assertEquals(monitorsUsedViewport, window0Rect); + } + + Thread.sleep(duration); + + window0.setFullscreen(false); + + window0Rect = new Rectangle(window0.getX(), window0.getY(), window0.getWidth(), window0.getHeight()); + monitor = window0.getMainMonitor(); + System.err.println("Test.2: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.2: Window monitor: "+monitor.getViewport()); + + Thread.sleep(duration); + anim.stop(); + destroyWindow(window0); + Assert.assertEquals(false,window0.isVisible()); + Assert.assertEquals(false,window0.isNativeValid()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + MonitorDevice monitor = window.getMainMonitor(); + List monitorModes = monitor.getSupportedModes(); + if(monitorModes.size()==1) { // no support .. System.err.println("Your platform has no ScreenMode change support, sorry"); destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); + Assert.assertTrue(monitorModes.size()>0); Animator animator = new Animator(window); animator.start(); - ScreenMode smCurrent = screen.getCurrentScreenMode(); - Assert.assertNotNull(smCurrent); - ScreenMode smOrig = screen.getOriginalScreenMode(); - Assert.assertNotNull(smOrig); - Assert.assertEquals(smCurrent, smOrig); - System.err.println("[0] current/orig: "+smCurrent); - - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 90); - if(null==screenModes) { + MonitorMode mmCurrent = monitor.getCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90); + if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) { // no rotation support .. System.err.println("Your platform has no rotation support, sorry"); destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); - Assert.assertNotNull(screenModes); - Assert.assertTrue(screenModes.size()>0); - - ScreenMode sm = (ScreenMode) screenModes.get(0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + MonitorMode sm = (MonitorMode) monitorModes.get(0); System.err.println("[0] set current: "+sm); - screen.setCurrentScreenMode(sm); - Assert.assertEquals(sm, screen.getCurrentScreenMode()); - Assert.assertNotSame(smOrig, screen.getCurrentScreenMode()); + monitor.setCurrentMode(sm); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(sm, monitor.getCurrentMode()); + Assert.assertNotSame(mmOrig, monitor.getCurrentMode()); + Assert.assertEquals(sm, monitor.queryCurrentMode()); Thread.sleep(waitTimeLong); @@ -167,11 +176,11 @@ public class TestScreenMode02NEWT extends UITestCase { Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] current/orig: "+mmCurrent); - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); + Assert.assertNotNull(mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); screen.destroy(); -- cgit v1.2.3 From c2a4905ec926362a08f486a68d428fb139821df1 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 7 Oct 2013 07:47:12 +0200 Subject: NEWT/OSX (Bug 836): Lifecycle operations performed on main-thread must be synchronized (wait-until-done) Wait-until-done (main thread): - WindowDriver.close0(..) - WindowDriver.initWindow0(..) Otherwise a re-queued operation (i.e. CALayer attachment) will mixup the order .. Experienced w/ fullscreen exit. --- .../jogamp/newt/driver/macosx/WindowDriver.java | 27 +++++----- src/newt/native/MacWindow.m | 59 +++++++++++++--------- 2 files changed, 48 insertions(+), 38 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 6aebf0410..d973c9005 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -86,7 +86,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = 0; isOffscreenInstance = false; if (0 != handle) { - OSXUtil.RunOnMainThread(false, new Runnable() { + OSXUtil.RunOnMainThread(true, new Runnable() { public void run() { close0( handle ); } } ); @@ -452,27 +452,28 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final PointImmutable pS, final int width, final int height, final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) { + final long parentWinHandle = getParentWindowHandle(); + final long preWinHandle = getWindowHandle(); + if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+ ": offscreen "+offscreenInstance+", recreate "+recreate+ ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+ - ", alwaysOnTop "+alwaysOnTop); + ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+ + ", surfaceHandle "+toHexString(surfaceHandle)); // Thread.dumpStack(); } try { - final long parentWin = getParentWindowHandle(); - if( 0 != getWindowHandle() ) { - final long thisWin = getWindowHandle(); + if( 0 != preWinHandle ) { setWindowHandle(0); - if( 0 == surfaceHandle ) { throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView"); } - OSXUtil.RunOnMainThread(false, new Runnable() { + OSXUtil.RunOnMainThread(true, new Runnable() { public void run() { - changeContentView0(parentWin, thisWin, 0); - close0( thisWin ); + changeContentView0(parentWinHandle, preWinHandle, 0); + close0( preWinHandle ); } } ); } else { if( 0 != surfaceHandle ) { @@ -494,13 +495,13 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl setWindowHandle( newWin ); final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; - // Non blocking initialization on main-thread! - OSXUtil.RunOnMainThread(false, new Runnable() { + // Blocking initialization on main-thread! + OSXUtil.RunOnMainThread(true, new Runnable() { public void run() { - initWindow0( parentWin, newWin, pS.getX(), pS.getY(), width, height, + initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, isOpaque, fullscreen, visible && !offscreenInstance, surfaceHandle); if( offscreenInstance ) { - orderOut0(0!=parentWin ? parentWin : newWin); + orderOut0(0!=parentWinHandle ? parentWinHandle : newWin); } else { setTitle0(newWin, getTitle()); setAlwaysOnTop0(getWindowHandle(), alwaysOnTop); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 1c7064a66..f8988cf15 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -764,27 +764,27 @@ NS_ENDHANDLER // specify we want mouse-moved events [myWindow setAcceptsMouseMovedEvents:YES]; - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); // Set the content view changeContentView(env, jthis, parentView, myWindow, myView, NO); - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); if(NULL!=parentWindow) { [myWindow attachToParent: parentWindow]; } - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d, visible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible], visible); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible], visible); // Immediately re-position this window based on an upper-left coordinate system setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); NS_DURING // concurrent view rendering @@ -793,8 +793,8 @@ NS_DURING [myWindow setAllowsConcurrentViewDrawing: YES]; } - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { [myView setCanDrawConcurrently: YES]; @@ -802,16 +802,16 @@ NS_DURING NS_HANDLER NS_ENDHANDLER - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); // visible on front if( visible ) { [myWindow orderFront: myWindow]; } - DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", - dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]); + DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", + dbgIdx++, myWindow, myView, [myWindow isVisible]); // force surface creation // [myView lockFocus]; @@ -831,16 +831,18 @@ NS_ENDHANDLER // right mouse button down events [myView setNextResponder: myWindow]; - DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView)); + DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", + dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); [myView setDestroyNotifySent: false]; setJavaWindowObject(env, jthis, myView, YES); - DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView)); + DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", + dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); [pool release]; + DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n", + (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); } /** @@ -857,14 +859,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); NewtView* mView = (NewtView *)[mWin contentView]; NSWindow* pWin = [mWin parentWindow]; - BOOL destroyNotifySent = (NULL != mView) ? [mView getDestroyNotifySent] : false; + BOOL destroyNotifySent, isNSView, isNewtView; + if( NULL != mView ) { + isNSView = [mView isKindOfClass:[NSView class]]; + isNewtView = [mView isKindOfClass:[NewtView class]]; + destroyNotifySent = isNewtView ? [mView getDestroyNotifySent] : false; + } else { + isNSView = false; + isNewtView = false; + destroyNotifySent = false; + } - DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n", - mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin); + DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], parent %p\n", + mWin, destroyNotifySent, mView, isNSView, isNewtView, pWin); [mWin setRealized: NO]; - if(NULL!=mView) { + if( isNewtView ) { // cleanup view [mView setDestroyNotifySent: true]; setJavaWindowObject(env, NULL, mView, NO); @@ -892,8 +903,7 @@ NS_ENDHANDLER } [mWin orderOut: mWin]; - DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", - mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); + DBG_PRINT( "windowClose.1 - %p view %p, parent %p\n", mWin, mView, pWin); // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. @@ -953,7 +963,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 #ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; #endif - DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; -- cgit v1.2.3 From 85878162940067b39b17c71878446dff0759040d Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 1 Nov 2013 01:25:32 +0100 Subject: Bug 882 - Crash on OSX when closing NEWT window - Fix: Release NewtMacWindow manually in close0() Release NewtMacWindow manually in close0() - Mark [NewtMacWindow setReleasedWhenClosed: NO] in init0(..) - Release NewtMacWindow manually in close0(..) Check pointer args in close0(..) --- make/scripts/tests.sh | 4 +- src/newt/native/MacWindow.m | 28 +++-- .../newt/DemoCreateAndDisposeOnCloseNEWT.java | 140 +++++++++++++++++++++ 3 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index b03f0fa68..641c3a906 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -327,7 +327,7 @@ function testawtswt() { # av demos # #testnoawt jogamp.opengl.openal.av.ALDummyUsage $* -testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $* # @@ -557,6 +557,8 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageAWT $* #testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT +testnoawt com.jogamp.opengl.test.junit.newt.DemoCreateAndDisposeOnCloseNEWT $* +#testawt com.jogamp.opengl.test.junit.newt.DemoCreateAndDisposeOnCloseNEWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index f8988cf15..f0ed170f0 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -716,8 +716,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 rectWin = NSMakeRect(x, y, w, h); } - [myWindow setReleasedWhenClosed: YES]; // default + [myWindow setReleasedWhenClosed: NO]; // We control NSWindow destruction! [myWindow setPreservesContentDuringLiveResize: NO]; +NS_DURING + if ( [myWindow respondsToSelector:@selector(setRestorable:)] ) { + // Available >= 10.7 - Removes restauration 'feature', really close + [myWindow setRestorable: NO]; + } +NS_HANDLER +NS_ENDHANDLER NSObject* nsParentObj = (NSObject*) ((intptr_t) parent); NSWindow* parentWindow = NULL; @@ -857,8 +864,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n"); + return; + } + BOOL isNSWin = [mWin isKindOfClass:[NSWindow class]]; + BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]]; + NSWindow *pWin = [mWin parentWindow]; + DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); + if( !isNewtWin ) { + DBG_PRINT( "windowClose.0 - Not a NEWT win - abort\n"); + return; + } NewtView* mView = (NewtView *)[mWin contentView]; - NSWindow* pWin = [mWin parentWindow]; BOOL destroyNotifySent, isNSView, isNewtView; if( NULL != mView ) { isNSView = [mView isKindOfClass:[NSView class]]; @@ -905,11 +923,7 @@ NS_ENDHANDLER DBG_PRINT( "windowClose.1 - %p view %p, parent %p\n", mWin, mView, pWin); - // Only release window, if release is not yet in process. - // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. - if(!destroyNotifySent) { - [mWin release]; - } + [mWin release]; DBG_PRINT( "windowClose.Xp\n"); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java new file mode 100644 index 000000000..e82204fd0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java @@ -0,0 +1,140 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.newt; + +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; + +/** + * Manual test case validating closing behavior. + *

    + * Validates bugs: + *

      + *
    • Bug 882: Crash on OSX when closing NEWT window
    • + *
    + *

    + * + */ +public class DemoCreateAndDisposeOnCloseNEWT { + public static void main(String[] args) { + int closeMode = 0; // 0 - none, 1 - window, animator, 2 - animator, window, 3 - System.exit + + for(int i=0; i Date: Mon, 2 Dec 2013 05:39:01 +0100 Subject: Bug 914: Newt OSX: Don't use exclusive fullscreen mode (captured display) in favor of proper WM incl. ALT-TAB app-switching --- make/scripts/tests.sh | 2 +- src/newt/native/MacWindow.m | 13 +++++++++++++ src/newt/native/NewtMacWindow.h | 3 +++ src/newt/native/NewtMacWindow.m | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 56a07e768..915752bef 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -90,7 +90,7 @@ function jrun() { #D_ARGS="-Djogl.debug=all" #D_ARGS="-Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" - D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" + #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index f0ed170f0..3e8935787 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -827,8 +827,21 @@ NS_ENDHANDLER NS_DURING // Available >= 10.5 - Makes the menubar disapear if( fullscreen ) { + /** + * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) + * allowing ALT-TAB to allow process/app switching! + * Shall have no penalty on modern GPU and is also recommended, see bottom box @ + * + * if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { [myView enterFullScreenMode: myScreen withOptions:NULL]; + } */ + if ( 0 != myView->fullscreenPresentationOptions ) { + [NSApp setPresentationOptions: myView->fullscreenPresentationOptions]; + } + } else { + if ( 0 != myView->defaultPresentationOptions ) { + [NSApp setPresentationOptions: myView->defaultPresentationOptions]; } } NS_HANDLER diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index c9d53f53b..a3bd5c41b 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -64,6 +64,9 @@ volatile NSTrackingRectTag ptrTrackingTag; NSRect ptrRect; NSCursor * myCursor; +@public + NSUInteger defaultPresentationOptions; + NSUInteger fullscreenPresentationOptions; } - (id)initWithFrame:(NSRect)frameRect; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 686e5d2b0..266b63081 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -129,6 +129,27 @@ static jmethodID windowRepaintID = NULL; */ myCursor = NULL; + // OSX 10.6 + if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && + [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { + defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; + fullscreenPresentationOptions = + // NSApplicationPresentationDefault| + // NSApplicationPresentationAutoHideDock| + NSApplicationPresentationHideDock| + // NSApplicationPresentationAutoHideMenuBar| + NSApplicationPresentationHideMenuBar| + NSApplicationPresentationDisableAppleMenu| + // NSApplicationPresentationDisableProcessSwitching| + // NSApplicationPresentationDisableSessionTermination| + NSApplicationPresentationDisableHideApplication| + // NSApplicationPresentationDisableMenuBarTransparency| + 0 ; + } else { + defaultPresentationOptions = 0; + fullscreenPresentationOptions = 0; + } + DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]); return res; } -- cgit v1.2.3 From 0237bde0f3c13d393c3942b41f79656a80fd578d Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 3 Dec 2013 21:54:57 +0100 Subject: Bug 914: Newt OSX: Reset NSApp's presentationOptions @ windowClose0() / Assume having focus in fullscreen-mode - Reset NSApp's presentationOptions @ windowClose0() Commit 69c334448cfe8af553fd97689137ecf8f996b378 started using the [NSApp setPresentationOptions: opts] but missed to reset to defaults @ windowClose0(); - Assume having focus in fullscreen-mode NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode! Note: OSX Fullscreen from a browser still shows the browser title-bar until mouse-click. Don't know how to avoid this. Minor issue.. --- src/newt/classes/jogamp/newt/WindowImpl.java | 14 ++--- .../jogamp/newt/driver/macosx/WindowDriver.java | 15 ++++-- src/newt/native/MacWindow.m | 63 +++++++++++++--------- src/newt/native/NewtMacWindow.h | 8 +-- src/newt/native/NewtMacWindow.m | 47 ++++++++-------- 5 files changed, 84 insertions(+), 63 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index d62a19f44..21343b263 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -674,37 +674,37 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( 0 != ( FLAG_CHANGE_PARENTING & flags) ) { sb.append("*"); } - sb.append("PARENT_"); + sb.append("PARENT "); sb.append(0 != ( FLAG_HAS_PARENT & flags)); sb.append(", "); if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { sb.append("*"); } - sb.append("FS_"); + sb.append("FS "); sb.append(0 != ( FLAG_IS_FULLSCREEN & flags)); - sb.append("_span_"); + sb.append("[span "); sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags)); - sb.append(", "); + sb.append("], "); if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) { sb.append("*"); } - sb.append("UNDECOR_"); + sb.append("UNDECOR "); sb.append(0 != ( FLAG_IS_UNDECORATED & flags)); sb.append(", "); if( 0 != ( FLAG_CHANGE_ALWAYSONTOP & flags) ) { sb.append("*"); } - sb.append("ALWAYSONTOP_"); + sb.append("ALWAYSONTOP "); sb.append(0 != ( FLAG_IS_ALWAYSONTOP & flags)); sb.append(", "); if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { sb.append("*"); } - sb.append("VISIBLE_"); + sb.append("VISIBLE "); sb.append(0 != ( FLAG_IS_VISIBLE & flags)); sb.append("]"); diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 7db3e2aab..641d7437c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -170,14 +170,20 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected void requestFocusImpl(final boolean force) { + final boolean _isFullscreen = isFullscreen(); + final boolean _isOffscreenInstance = isOffscreenInstance; if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+isOffscreenInstance); + System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen); } - if(!isOffscreenInstance) { + if(!_isOffscreenInstance) { OSXUtil.RunOnMainThread(false, new Runnable() { @Override public void run() { requestFocus0(getWindowHandle(), force); + if(_isFullscreen) { + // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode! + focusChanged(false, true); + } } } ); } else { focusChanged(false, true); @@ -516,7 +522,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override public void run() { initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, - isOpaque, fullscreen, visible && !offscreenInstance, surfaceHandle); + isOpaque, visible && !offscreenInstance, surfaceHandle); if( offscreenInstance ) { orderOut0(0!=parentWinHandle ? parentWinHandle : newWin); } else { @@ -534,8 +540,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native long createView0(int x, int y, int w, int h, boolean fullscreen); private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view); /** Must be called on Main-Thread */ - private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, boolean visible, long view); + private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, boolean opaque, boolean visible, long view); private native boolean lockSurface0(long window, long view); private native boolean unlockSurface0(long window, long view); /** Must be called on Main-Thread */ diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 3e8935787..30d3458ad 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -693,11 +693,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, - jboolean opaque, jboolean fullscreen, jboolean visible, jlong jview) + jboolean opaque, jboolean visible, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); NewtView* myView = (NewtView*) (intptr_t) jview ; + BOOL fullscreen = myWindow->isFullscreenWindow; DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, view %p (START)\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, @@ -824,8 +825,20 @@ NS_ENDHANDLER // [myView lockFocus]; // [myView unlockFocus]; + // Set the next responder to be the window so that we can forward + // right mouse button down events + [myView setNextResponder: myWindow]; + + DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", + dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); + + [myView setDestroyNotifySent: false]; + setJavaWindowObject(env, jthis, myView, YES); + + DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", + dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); + NS_DURING - // Available >= 10.5 - Makes the menubar disapear if( fullscreen ) { /** * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) @@ -834,29 +847,18 @@ NS_DURING * * if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { + // Available >= 10.5 - Makes the menubar disapear [myView enterFullScreenMode: myScreen withOptions:NULL]; } */ - if ( 0 != myView->fullscreenPresentationOptions ) { - [NSApp setPresentationOptions: myView->fullscreenPresentationOptions]; - } - } else { - if ( 0 != myView->defaultPresentationOptions ) { - [NSApp setPresentationOptions: myView->defaultPresentationOptions]; + if( myWindow->hasPresentationSwitch ) { + DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n", + dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions); + [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions]; } } NS_HANDLER NS_ENDHANDLER - // Set the next responder to be the window so that we can forward - // right mouse button down events - [myView setNextResponder: myWindow]; - - DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); - - [myView setDestroyNotifySent: false]; - setJavaWindowObject(env, jthis, myView, YES); - DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); @@ -890,6 +892,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 return; } NewtView* mView = (NewtView *)[mWin contentView]; + BOOL fullscreen = mWin->isFullscreenWindow; BOOL destroyNotifySent, isNSView, isNewtView; if( NULL != mView ) { isNSView = [mView isKindOfClass:[NSView class]]; @@ -901,8 +904,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 destroyNotifySent = false; } - DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], parent %p\n", - mWin, destroyNotifySent, mView, isNSView, isNewtView, pWin); + DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], fullscreen %d, parent %p\n", + mWin, destroyNotifySent, mView, isNSView, isNewtView, (int)fullscreen, pWin); [mWin setRealized: NO]; @@ -913,8 +916,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 } NS_DURING + /** + * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) + * See initWindow0(..) above .. if(NULL!=mView) { - // Available >= 10.5 - Makes the menubar disapear BOOL iifs; if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) { iifs = [mView isInFullScreenMode]; @@ -924,7 +929,15 @@ NS_DURING if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [mView exitFullScreenModeWithOptions: NULL]; } - // Note: mWin's release will also release it's mView! + } */ + // Note: mWin's release will also release it's mView! + DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n", + mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions); + + if( fullscreen && mWin->hasPresentationSwitch ) { + DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n", + mWin, mView, (int)mWin->defaultPresentationOptions); + [NSApp setPresentationOptions: mWin->defaultPresentationOptions]; } NS_HANDLER NS_ENDHANDLER @@ -934,7 +947,7 @@ NS_ENDHANDLER } [mWin orderOut: mWin]; - DBG_PRINT( "windowClose.1 - %p view %p, parent %p\n", mWin, mView, pWin); + DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin); [mWin release]; @@ -1208,7 +1221,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); - DBG_PRINT( "setAlwaysOnTop0 - window: %p (START)\n", win); + DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop); if(atop) { [win setLevel:NSFloatingWindowLevel]; @@ -1216,7 +1229,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo [win setLevel:NSNormalWindowLevel]; } - DBG_PRINT( "setAlwaysOnTop0 - window: %p (END)\n", win); + DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop); [pool release]; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index a3bd5c41b..ba60b5665 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -64,9 +64,6 @@ volatile NSTrackingRectTag ptrTrackingTag; NSRect ptrRect; NSCursor * myCursor; -@public - NSUInteger defaultPresentationOptions; - NSUInteger fullscreenPresentationOptions; } - (id)initWithFrame:(NSRect)frameRect; @@ -113,7 +110,6 @@ @interface NewtMacWindow : NSWindow #endif { - BOOL isFullscreenWindow; BOOL mouseConfined; BOOL mouseVisible; BOOL mouseInside; @@ -122,6 +118,10 @@ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command NSPoint lastInsideMousePosition; @public + BOOL hasPresentationSwitch; + NSUInteger defaultPresentationOptions; + NSUInteger fullscreenPresentationOptions; + BOOL isFullscreenWindow; int cachedInsets[4]; // l, r, t, b } diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 266b63081..4b0198c7e 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -129,27 +129,6 @@ static jmethodID windowRepaintID = NULL; */ myCursor = NULL; - // OSX 10.6 - if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && - [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { - defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; - fullscreenPresentationOptions = - // NSApplicationPresentationDefault| - // NSApplicationPresentationAutoHideDock| - NSApplicationPresentationHideDock| - // NSApplicationPresentationAutoHideMenuBar| - NSApplicationPresentationHideMenuBar| - NSApplicationPresentationDisableAppleMenu| - // NSApplicationPresentationDisableProcessSwitching| - // NSApplicationPresentationDisableSessionTermination| - NSApplicationPresentationDisableHideApplication| - // NSApplicationPresentationDisableMenuBarTransparency| - 0 ; - } else { - defaultPresentationOptions = 0; - fullscreenPresentationOptions = 0; - } - DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]); return res; } @@ -466,6 +445,29 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { styleMask: windowStyle backing: bufferingType defer: deferCreation]; + // OSX 10.6 + if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && + [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { + hasPresentationSwitch = YES; + defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; + fullscreenPresentationOptions = + // NSApplicationPresentationDefault| + // NSApplicationPresentationAutoHideDock| + NSApplicationPresentationHideDock| + // NSApplicationPresentationAutoHideMenuBar| + NSApplicationPresentationHideMenuBar| + NSApplicationPresentationDisableAppleMenu| + // NSApplicationPresentationDisableProcessSwitching| + // NSApplicationPresentationDisableSessionTermination| + NSApplicationPresentationDisableHideApplication| + // NSApplicationPresentationDisableMenuBarTransparency| + // NSApplicationPresentationFullScreen| // OSX 10.7 + 0 ; + } else { + hasPresentationSwitch = NO; + defaultPresentationOptions = 0; + fullscreenPresentationOptions = 0; + } isFullscreenWindow = isfs; // Why is this necessary? Without it we don't get any of the // delegate methods like resizing and window movement. @@ -483,7 +485,8 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { mouseInside = NO; cursorIsHidden = NO; realized = YES; - DBG_PRINT("NewtWindow::create: %p, realized %d (refcnt %d)\n", res, realized, (int)[res retainCount]); + DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n", + res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]); return res; } -- cgit v1.2.3 From e7ffa68bce9bb707005be72530b207c732f62c31 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 31 Dec 2013 08:14:21 +0100 Subject: Bug 934, Bug 935: NEWT: Add support for custom Application/Window and Pointer Icons - Utilizing JOGL's PNG decoder for all icons, if available. - Application/window icons: - Providing default application/window icons in 16x16 and 32x32 size - NewtFactory.setWindowIcons(..) or property 'newt.window.icons' maybe used to override default icons. - Using icons at application/window instantiation - Display.PointerIcons: - NativeWindow Win32 WindowClass no more references a default cursor in favor of fine grained cursor control [in NEWT] - Display provides create/destroy methods, where display destruction also releases open PointerIcon references. - Window.setPointerIcon(..) sets custom PointerIcon - Implemented Platforms - X11 - Windows - OSX - Manual Test: TestGearsES2NEWT (Press 'c') --- make/build-jogl.xml | 2 +- make/build-newt.xml | 12 +- .../resources/assets-test/jogamp-pointer-64x64.png | Bin 0 -> 2843 bytes make/resources/assets/newt/data/jogamp-16x16.png | Bin 0 -> 549 bytes make/resources/assets/newt/data/jogamp-32x32.png | Bin 0 -> 1020 bytes make/resources/misc/jogamp-48x48.png | Bin 0 -> 1278 bytes make/resources/misc/jogamp-64x64.png | Bin 0 -> 1833 bytes make/scripts/tests-win.bat | 4 +- make/scripts/tests-x64-dbg.bat | 3 +- make/scripts/tests.sh | 5 +- src/nativewindow/native/win32/GDImisc.c | 2 +- src/newt/classes/com/jogamp/newt/Display.java | 50 +++++++- src/newt/classes/com/jogamp/newt/NewtFactory.java | 33 +++++ src/newt/classes/com/jogamp/newt/Window.java | 15 +++ .../classes/com/jogamp/newt/opengl/GLWindow.java | 11 ++ src/newt/classes/jogamp/newt/DisplayImpl.java | 68 +++++++++- src/newt/classes/jogamp/newt/WindowImpl.java | 22 ++++ src/newt/classes/jogamp/newt/driver/PNGIcon.java | 102 +++++++++++++++ .../jogamp/newt/driver/macosx/DisplayDriver.java | 51 ++++++++ .../jogamp/newt/driver/macosx/WindowDriver.java | 11 ++ .../jogamp/newt/driver/opengl/JoglUtilPNGIcon.java | 139 +++++++++++++++++++++ .../jogamp/newt/driver/windows/DisplayDriver.java | 38 ++++++ .../jogamp/newt/driver/windows/WindowDriver.java | 56 +++++++-- .../jogamp/newt/driver/x11/DisplayDriver.java | 46 +++++++ .../jogamp/newt/driver/x11/WindowDriver.java | 51 +++++++- src/newt/native/MacWindow.m | 73 ++++++++++- src/newt/native/NewtMacWindow.h | 4 +- src/newt/native/NewtMacWindow.m | 41 ++++-- src/newt/native/WindowsWindow.c | 115 ++++++++++++++++- src/newt/native/X11Display.c | 52 ++++++++ src/newt/native/X11Window.c | 35 +++++- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 29 ++++- 32 files changed, 1027 insertions(+), 43 deletions(-) create mode 100644 make/resources/assets-test/jogamp-pointer-64x64.png create mode 100644 make/resources/assets/newt/data/jogamp-16x16.png create mode 100644 make/resources/assets/newt/data/jogamp-32x32.png create mode 100644 make/resources/misc/jogamp-48x48.png create mode 100644 make/resources/misc/jogamp-64x64.png create mode 100644 src/newt/classes/jogamp/newt/driver/PNGIcon.java create mode 100644 src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/build-jogl.xml b/make/build-jogl.xml index 28b738b10..4cdb93f4d 100644 --- a/make/build-jogl.xml +++ b/make/build-jogl.xml @@ -1833,7 +1833,7 @@ - + + value="com/jogamp/newt/opengl/** jogamp/newt/driver/opengl/**"/> @@ -277,12 +277,14 @@ + + @@ -302,6 +304,7 @@ + @@ -309,6 +312,7 @@ + @@ -316,6 +320,7 @@ + @@ -323,6 +328,7 @@ + @@ -332,18 +338,21 @@ + + + @@ -798,6 +807,7 @@ + diff --git a/make/resources/assets-test/jogamp-pointer-64x64.png b/make/resources/assets-test/jogamp-pointer-64x64.png new file mode 100644 index 000000000..a965dcab1 Binary files /dev/null and b/make/resources/assets-test/jogamp-pointer-64x64.png differ diff --git a/make/resources/assets/newt/data/jogamp-16x16.png b/make/resources/assets/newt/data/jogamp-16x16.png new file mode 100644 index 000000000..02df8997f Binary files /dev/null and b/make/resources/assets/newt/data/jogamp-16x16.png differ diff --git a/make/resources/assets/newt/data/jogamp-32x32.png b/make/resources/assets/newt/data/jogamp-32x32.png new file mode 100644 index 000000000..ab21c6e1b Binary files /dev/null and b/make/resources/assets/newt/data/jogamp-32x32.png differ diff --git a/make/resources/misc/jogamp-48x48.png b/make/resources/misc/jogamp-48x48.png new file mode 100644 index 000000000..216f8c0b7 Binary files /dev/null and b/make/resources/misc/jogamp-48x48.png differ diff --git a/make/resources/misc/jogamp-64x64.png b/make/resources/misc/jogamp-64x64.png new file mode 100644 index 000000000..9936616ca Binary files /dev/null and b/make/resources/misc/jogamp-64x64.png differ diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat index f5417bf7a..d95b0025f 100755 --- a/make/scripts/tests-win.bat +++ b/make/scripts/tests-win.bat @@ -6,7 +6,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersion REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000 @@ -39,7 +39,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintin REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT %* -scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %* +REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT %* diff --git a/make/scripts/tests-x64-dbg.bat b/make/scripts/tests-x64-dbg.bat index 6e8407f3e..ce2df922c 100755 --- a/make/scripts/tests-x64-dbg.bat +++ b/make/scripts/tests-x64-dbg.bat @@ -55,9 +55,10 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer" "-Djogl.debug.TileRenderer.PNG" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer" REM set D_ARGS="-Djogl.gljpanel.noverticalflip" +set D_ARGS="-Dnewt.debug=all" REM set D_ARGS="-Dnewt.debug.Window" REM set D_ARGS="-Dnewt.debug.Window.KeyEvent" -set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Window.KeyEvent" "-Dnewt.debug.EDT" +REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Window.KeyEvent" "-Dnewt.debug.EDT" REM set D_ARGS="-Dnewt.debug.Window.MouseEvent" REM set D_ARGS="-Dnewt.debug.Window.MouseEvent" "-Dnewt.debug.Window.KeyEvent" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 6cb1966d1..4c084d705 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -312,7 +312,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* # # demos (any TK, more user driven tests) @@ -325,7 +325,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NEWT $* #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $* @@ -636,6 +636,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGTextureFromFileNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.ToolPNG2CSource $* #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestGLReadBufferUtilTextureIOWrite01AWT $* diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c index b55988c11..25b98acf3 100644 --- a/src/nativewindow/native/win32/GDImisc.c +++ b/src/nativewindow/native/win32/GDImisc.c @@ -263,7 +263,7 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass0 wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; - wc.hCursor = LoadCursor( NULL, IDC_ARROW); + wc.hCursor = NULL; wc.hbrBackground = NULL; // no background paint - GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = clazzName; diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 4469189a8..ee6dfd080 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -28,15 +28,21 @@ package com.jogamp.newt; -import com.jogamp.newt.util.EDTUtil; -import jogamp.newt.Debug; - +import java.io.IOException; import java.lang.ref.WeakReference; -import java.util.*; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; +import jogamp.newt.Debug; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.util.EDTUtil; + public abstract class Display { public static final boolean DEBUG = Debug.debug("Display"); @@ -55,6 +61,42 @@ public abstract class Display { return false; } + /** + * Native PointerIcon handle. + *

    + * Instances can be created via {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int)} + * and released via {@link Display#destroyPointerIcon(PointerIcon)}. + *

    + *

    + * PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}. + *

    + */ + public static interface PointerIcon { } + + /** + * Returns the created {@link PointerIcon} or null if not implemented on platform. + * + * @param pngResource PNG resource + * @param hotX pointer hotspot x-coord, origin is upper-left corner + * @param hotY pointer hotspot y-coord, origin is upper-left corner + * @throws MalformedURLException + * @throws InterruptedException + * @throws IOException + * + * @see PointerIcon + * @see #destroyPointerIcon(PointerIcon) + * @see Window#setPointerIcon(PointerIcon) + */ + + public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException; + + /** + * @param pi + * + * @see #createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) + */ + public abstract void destroyPointerIcon(PointerIcon pi); + /** * Manual trigger the native creation, if it is not done yet.
    * This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsDevice}, via diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 157e2bb3c..92339ea73 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -36,6 +36,7 @@ package com.jogamp.newt; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Arrays; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -44,6 +45,8 @@ import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowFactory; +import com.jogamp.common.util.IOUtil; + import jogamp.newt.Debug; import jogamp.newt.DisplayImpl; import jogamp.newt.ScreenImpl; @@ -54,15 +57,45 @@ public class NewtFactory { public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver"; + private static IOUtil.ClassResources defaultWindowIcons; + static { AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { NativeWindowFactory.initSingleton(); // last resort .. + { + final String[] paths = Debug.getProperty("newt.window.icons", true, "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png").split("\\s"); + if( paths.length < 2 ) { + throw new IllegalArgumentException("Property 'newt.window.icons' did not specify at least two PNG icons, but "+Arrays.toString(paths)); + } + final Class clazz = NewtFactory.class; + defaultWindowIcons = new IOUtil.ClassResources(clazz, paths); + } return null; } } ); } + /** + * Returns the application window icon resources to be used. + *

    + * Property newt.window.icons may define a list of PNG icons separated by a whitespace character. + * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution. + *

    + *

    + * Users may also specify application window icons using {@link #setWindowIcons(com.jogamp.common.util.IOUtil.ClassResources)}. + *

    + */ + public static IOUtil.ClassResources getWindowIcons() { return defaultWindowIcons; } + + /** + * Allow user to set custom window icons, only applicable at application start before creating any NEWT instance. + *

    + * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution. + *

    + */ + public static void setWindowIcons(IOUtil.ClassResources cres) { defaultWindowIcons = cres; } + public static Class getCustomClass(String packageName, String classBaseName) { Class clazz = null; if(packageName!=null && classBaseName!=null) { diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 5c3bb7889..8e73ba1d2 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -30,6 +30,7 @@ package com.jogamp.newt; import java.util.List; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.event.GestureHandler; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; @@ -307,6 +308,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol { */ void setPointerVisible(boolean pointerVisible); + /** + * Returns the current {@link PointerIcon}, which maybe null for the default. + * @see #setPointerIcon(PointerIcon) + */ + PointerIcon getPointerIcon(); + + /** + * @param pi Valid {@link PointerIcon} reference or null to reset the pointer icon to default. + * + * @see PointerIcon + * @see Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) + */ + void setPointerIcon(final PointerIcon pi); + /** @see #confinePointer(boolean) */ boolean isPointerConfined(); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 208602aa1..ca8ab6733 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -77,6 +77,7 @@ import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.event.GestureHandler; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseListener; @@ -267,6 +268,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind window.setPointerVisible(mouseVisible); } + @Override + public final PointerIcon getPointerIcon() { + return window.getPointerIcon(); + } + + @Override + public final void setPointerIcon(final PointerIcon pi) { + window.setPointerIcon(pi); + } + @Override public final boolean isPointerConfined() { return window.isPointerConfined(); diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index 0c29d772a..4e9b8b441 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -34,14 +34,18 @@ package jogamp.newt; +import com.jogamp.common.util.IOUtil; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.NEWTEvent; import com.jogamp.newt.event.NEWTEventConsumer; import jogamp.newt.event.NEWTEventTask; + import com.jogamp.newt.util.EDTUtil; +import java.io.IOException; +import java.net.MalformedURLException; import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -62,6 +66,67 @@ public abstract class DisplayImpl extends Display { }); } + public static class PointerIconImpl implements PointerIcon { + public final long handle; + public PointerIconImpl(long handle) { + this.handle=handle; + } + } + + private void addPointerIconToList(final PointerIcon pi) { + synchronized(pointerIconList) { + pointerIconList.add(pi); + } + } + private void delPointerIconFromList(final PointerIcon pi) { + synchronized(pointerIconList) { + pointerIconList.remove(pi); + } + } + private final ArrayList pointerIconList = new ArrayList(); + + /** Executed from EDT! */ + private void destroyAllPointerIconFromList(final long dpy) { + synchronized(pointerIconList) { + for( int i=0; i < pointerIconList.size(); i++ ) { + final PointerIcon item = pointerIconList.get(i); + if( null != item ) { + // destroy! + destroyPointerIconImpl(dpy, item); + } + } + pointerIconList.clear(); + } + } + + @Override + public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + final PointerIcon res = createPointerIconImpl(pngResource, hotX, hotY); + addPointerIconToList(res); + return res; + } + protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + return null; + } + + @Override + public final void destroyPointerIcon(final PointerIcon pi) { + delPointerIconFromList(pi); + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + @Override + public Object run(long dpy) { + try { + destroyPointerIconImpl(dpy, pi); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + }); + } + /** Executed from EDT! */ + protected void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { } + /** Ensure static init has been run. */ /* pp */static void initSingleton() { } @@ -283,6 +348,7 @@ public abstract class DisplayImpl extends Display { @Override public void run() { if ( null != f_aDevice ) { + f_dpy.destroyAllPointerIconFromList(f_aDevice.getHandle()); f_dpy.closeNativeImpl(f_aDevice); } } @@ -453,7 +519,7 @@ public abstract class DisplayImpl extends Display { /** Dispatch native Toolkit messageges */ protected abstract void dispatchMessagesNative(); - private Object eventsLock = new Object(); + private final Object eventsLock = new Object(); private ArrayList events = new ArrayList(); private volatile boolean haveEvents = false; diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 7a7e69e48..d078caa3b 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -42,6 +42,7 @@ import java.lang.reflect.Method; import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.IntBitfield; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Display; @@ -83,6 +84,7 @@ import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; import jogamp.nativewindow.SurfaceUpdatedHelper; +import jogamp.newt.DisplayImpl.PointerIconImpl; public abstract class WindowImpl implements Window, NEWTEventConsumer { @@ -170,6 +172,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private String title = "Newt Window"; private boolean undecorated = false; private boolean alwaysOnTop = false; + private PointerIcon pointerIcon = null; private boolean pointerVisible = true; private boolean pointerConfined = false; private LifecycleHook lifecycleHook = null; @@ -436,6 +439,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer createNativeImpl(); screen.addMonitorModeListener(monitorModeListenerImpl); setTitleImpl(title); + if( null != pointerIcon ) { + setPointerIcon(pointerIcon); + } setPointerVisibleImpl(pointerVisible); confinePointerImpl(pointerConfined); setKeyboardVisible(keyboardVisible); @@ -725,6 +731,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected boolean setPointerVisibleImpl(boolean pointerVisible) { return false; } protected boolean confinePointerImpl(boolean confine) { return false; } protected void warpPointerImpl(int x, int y) { } + protected void setPointerIconImpl(final PointerIconImpl pi) { } //---------------------------------------------------------------------- // NativeSurface @@ -1675,6 +1682,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } + + @Override + public final PointerIcon getPointerIcon() { return pointerIcon; } + + @Override + public final void setPointerIcon(final PointerIcon pi) { + if( this.pointerIcon != pi ) { + setPointerIcon(pointerIcon); + if( isNativeValid() ) { + setPointerIconImpl((PointerIconImpl)pi); + } + this.pointerIcon = pi; + } + } + @Override public final boolean isPointerConfined() { return pointerConfined; diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java new file mode 100644 index 000000000..c958f6ec2 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java @@ -0,0 +1,102 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.newt.driver; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.ByteBuffer; + +import jogamp.newt.Debug; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.ReflectionUtil; + +public class PNGIcon { + private static final String err0 = "PNG decoder not implemented."; + + private static final boolean avail; + + static { + Debug.initSingleton(); + + final ClassLoader cl = PNGIcon.class.getClassLoader(); + avail = ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl) && + ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.texture.spi.PNGImage", cl); + } + + /** Returns true if PNG decoder is available. */ + public static boolean isAvailable() { + return avail; + } + + /** + * Implemented for X11. + * @param resources + * @param data_size + * @param elem_bytesize + * + * @return BGRA8888 bytes with origin at upper-left corner where component B is located on the lowest 8-bit and component A is located on the highest 8-bit. + * + * @throws UnsupportedOperationException if not implemented + * @throws InterruptedException + * @throws IOException + * @throws MalformedURLException + */ + public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException { + if( avail ) { + return jogamp.newt.driver.opengl.JoglUtilPNGIcon.arrayToX11BGRAImages(resources, data_size, elem_bytesize); + } + throw new UnsupportedOperationException(err0); + } + + /** + * Implemented for Windows. + * @param resources + * @param toBGRA if true, arranges stores in BGRA888 order, otherwise RGBA888 + * @param width + * @param height + * @param data_size + * @param elem_bytesize + * @param resourcesIdx + * @return pixels with origin at upper-left corner. + * If storing RGBA8888, component R is located on the lowest 8-bit. + * If storing BGRA8888, component B is located on the lowest 8-bit. + * Component A is located on the highest 8-bit. + * + * @throws UnsupportedOperationException if not implemented + * @throws InterruptedException + * @throws IOException + * @throws MalformedURLException + */ + public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException { + if( avail ) { + return jogamp.newt.driver.opengl.JoglUtilPNGIcon.singleToRGBAImage(resources, resourceIdx, toBGRA, width, height, data_size, elem_bytesize); + } + throw new UnsupportedOperationException(err0); + } +} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java index c44685dc8..86c8464a8 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -34,15 +34,26 @@ package jogamp.newt.driver.macosx; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.Buffer; +import java.nio.ByteBuffer; + import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; +import com.jogamp.common.util.IOUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; +import com.jogamp.newt.NewtFactory; import jogamp.newt.DisplayImpl; import jogamp.newt.NEWTJNILibLoader; +import jogamp.newt.driver.PNGIcon; public class DisplayDriver extends DisplayImpl { + private static final int defaultIconWidth, defaultIconHeight; + private static final Buffer defaultIconData; + static { NEWTJNILibLoader.loadNEWT(); @@ -52,6 +63,25 @@ public class DisplayDriver extends DisplayImpl { if(!WindowDriver.initIDs0()) { throw new NativeWindowException("Failed to initialize jmethodIDs"); } + { + final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 }; + Buffer data=null; + if( PNGIcon.isAvailable() ) { + try { + final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons(); + data = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, false /* toBGRA */, width, height, data_size, elem_bytesize); + } catch (Exception e) { + e.printStackTrace(); + } + } + defaultIconWidth = width[0]; + defaultIconHeight = height[0]; + defaultIconData = data; + if( null != defaultIconData ) { + DisplayDriver.setAppIcon0(defaultIconData, defaultIconWidth, defaultIconHeight); + } + } + if(DEBUG) { System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName()); } @@ -79,6 +109,23 @@ public class DisplayDriver extends DisplayImpl { aDevice.close(); } + @Override + protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + if( PNGIcon.isAvailable() ) { + final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 }; + if( null != pngResource && 0 < pngResource.resourceCount() ) { + final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size, elem_bytesize); + return new PointerIconImpl( createPointerIcon0(data, width[0], height[0], hotX, hotY) ); + } + } + return null; + } + + @Override + protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { + destroyPointerIcon0(((PointerIconImpl)pi).handle); + } + public static void runNSApplication() { runNSApplication0(); } @@ -89,5 +136,9 @@ public class DisplayDriver extends DisplayImpl { private static native boolean initNSApplication0(); private static native void runNSApplication0(); private static native void stopNSApplication0(); + /* pp */ static native void setAppIcon0(Object iconData, int iconWidth, int iconHeight); + private static native long createPointerIcon0(Object iconData, int iconWidth, int iconHeight, int hotX, int hotY); + private static native long destroyPointerIcon0(long handle); + } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 641d7437c..a55fa915a 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -46,6 +46,7 @@ import javax.media.nativewindow.util.PointImmutable; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.newt.WindowImpl; +import jogamp.newt.DisplayImpl.PointerIconImpl; import jogamp.newt.driver.DriverClearFocus; import jogamp.newt.driver.DriverUpdatePosition; @@ -391,6 +392,15 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } } + @Override + protected void setPointerIconImpl(final PointerIconImpl pi) { + OSXUtil.RunOnMainThread(false, new Runnable() { + @Override + public void run() { + setPointerIcon0(getWindowHandle(), null != pi ? pi.handle : 0); + } } ); + } + @Override protected boolean setPointerVisibleImpl(final boolean pointerVisible) { if( !isOffscreenInstance ) { @@ -568,6 +578,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); private static native boolean confinePointer0(long windowHandle, boolean confine); private static native void warpPointer0(long windowHandle, int x, int y); + private static native void setPointerIcon0(long windowHandle, long handle); // Window styles private static final int NSBorderlessWindowMask = 0; diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java new file mode 100644 index 000000000..ea9029006 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java @@ -0,0 +1,139 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.newt.driver.opengl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.nio.ByteBuffer; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.texture.spi.PNGImage; + +public class JoglUtilPNGIcon { + + public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException { + final PNGImage[] images = new PNGImage[resources.resourceCount()]; + data_size[0] = 0; + for(int i=0; inull if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */ protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; } + @Override + protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + if( PNGIcon.isAvailable() ) { + final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 }; + if( null != pngResource && 0 < pngResource.resourceCount() ) { + final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, false /* toBGRA */, width, height, data_size, elem_bytesize); + final long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + @Override + public Long run(long dpy) { + long h = 0; + try { + h = createPointerIcon0(dpy, data, width[0], height[0], hotX, hotY); + } catch (Exception e) { + e.printStackTrace(); + } + return Long.valueOf(h); + } + }).longValue(); + return new PointerIconImpl(handle); + } + } + return null; + } + + @Override + protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { + destroyPointerIcon0(displayHandle, ((PointerIconImpl)pi).handle); + } + //---------------------------------------------------------------------- // Internals only // @@ -137,6 +174,15 @@ public class DisplayDriver extends DisplayImpl { private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now + static long createPointerIcon0(long display, Buffer data, int width, int height, int hotX, int hotY) { + if( !Buffers.isDirect(data) ) { + throw new IllegalArgumentException("data buffer is not direct "+data); + } + return createPointerIcon0(display, data, Buffers.getDirectBufferByteOffset(data), width, height, hotX, hotY); + } + private static native long createPointerIcon0(long display, Object data, int data_offset, int width, int height, int hotX, int hotY); + static native void destroyPointerIcon0(long display, long handle); + /** X11 Window delete atom marker used on EDT */ private long windowDeleteAtom; diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index f2a27b0c9..0ea2c5358 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -34,11 +34,16 @@ package jogamp.newt.driver.x11; +import java.nio.Buffer; + import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; import jogamp.newt.DisplayImpl; import jogamp.newt.DisplayImpl.DisplayRunnable; +import jogamp.newt.DisplayImpl.PointerIconImpl; import jogamp.newt.WindowImpl; +import jogamp.newt.driver.PNGIcon; + import javax.media.nativewindow.*; import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.util.Insets; @@ -47,6 +52,7 @@ import javax.media.nativewindow.util.Point; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; +import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.MouseEvent; @@ -58,8 +64,29 @@ public class WindowDriver extends WindowImpl { private static final int X11_WHEEL_TWO_UP_BUTTON = 6; private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7; + private static final int defaultIconDataSize; + private static final Buffer defaultIconData; + static { ScreenDriver.initSingleton(); + + int _icon_data_size=0, _icon_elem_bytesize=0; + Buffer _icon_data=null; + if( PNGIcon.isAvailable() ) { + try { + final int[] data_size = { 0 }, elem_bytesize = { 0 }; + _icon_data = PNGIcon.arrayToX11BGRAImages(NewtFactory.getWindowIcons(), data_size, elem_bytesize); + _icon_data_size = data_size[0]; + _icon_elem_bytesize = elem_bytesize[0]; + } catch (Exception e) { + e.printStackTrace(); + } + } + defaultIconDataSize = _icon_data_size; + defaultIconData = _icon_data; + if(DEBUG_IMPLEMENTATION) { + System.err.println("Def. Icon: data_size "+defaultIconDataSize+" * elem_size "+_icon_elem_bytesize+" = data "+defaultIconData); + } } public WindowDriver() { @@ -100,7 +127,8 @@ public class WindowDriver extends WindowImpl { setWindowHandle(CreateWindow0(getParentWindowHandle(), edtDevice.getHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); + getX(), getY(), getWidth(), getHeight(), autoPosition(), flags, + defaultIconDataSize, defaultIconData)); } finally { edtDevice.unlock(); } @@ -245,6 +273,21 @@ public class WindowDriver extends WindowImpl { }); } + @Override + protected void setPointerIconImpl(final PointerIconImpl pi) { + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + @Override + public Object run(long dpy) { + try { + setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.handle : 0); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + }); + } + @Override protected boolean setPointerVisibleImpl(final boolean pointerVisible) { return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { @@ -381,13 +424,17 @@ public class WindowDriver extends WindowImpl { private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, int visualID, long javaObjectAtom, long windowDeleteAtom, - int x, int y, int width, int height, boolean autoPosition, int flags); + int x, int y, int width, int height, boolean autoPosition, int flags, + int iconDataSize, Object iconData); private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, long windowDeleteAtom, int x, int y, int width, int height, int flags); private native void requestFocus0(long display, long windowHandle, boolean force); private static native void setTitle0(long display, long windowHandle, String title); + + private static native void setPointerIcon0(long display, long windowHandle, long handle); + private static native long getParentWindow0(long display, long windowHandle); private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible); private static native boolean confinePointer0(long display, long windowHandle, boolean grab); diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 30d3458ad..16e9814ef 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -285,6 +285,76 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic [pool release]; } +static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jiconWidth, jint jiconHeight) { + if( NULL != jiconData ) { + unsigned char * iconData = (unsigned char *) (*env)->GetDirectBufferAddress(env, jiconData); + NSInteger iconWidth = (NSInteger) jiconWidth; + NSInteger iconHeight = (NSInteger) jiconHeight; + const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp; + const NSBitmapFormat bfmt = NSAlphaNonpremultipliedBitmapFormat; + const BOOL hasAlpha = YES; + + NSBitmapImageRep* bir = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &iconData + pixelsWide: iconWidth + pixelsHigh: iconHeight + bitsPerSample: bpc + samplesPerPixel: spp + hasAlpha: hasAlpha + isPlanar: NO + colorSpaceName: NSCalibratedRGBColorSpace + bitmapFormat: bfmt + bytesPerRow: iconWidth*4 + bitsPerPixel: bpp]; + [bir autorelease]; + NSImage* nsImage = [[NSImage alloc] initWithCGImage: [bir CGImage] size:NSZeroSize]; + return nsImage; + } + return NULL; +} + +/* + * Class: jogamp_newt_driver_macosx_DisplayDriver + * Method: setAppIcon0 + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0 + (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight) +{ + NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); + if( NULL != nsImage ) { + [nsImage autorelease]; + [NSApp setApplicationIconImage: nsImage]; + } +} + +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0 + (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight, jint hotX, jint hotY) +{ + NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); + if( NULL != nsImage ) { + [nsImage autorelease]; + NSPoint hotP = { hotX, hotY }; + NSCursor * c = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; + return (jlong) (intptr_t) c; + } + return 0; +} + +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0 + (JNIEnv *env, jobject unused, jlong handle) +{ + NSCursor * c = (NSCursor*) (intptr_t) handle ; + [c release]; +} + +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 + (JNIEnv *env, jobject unused, jlong window, jlong handle) +{ + NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; + NSCursor * c = (NSCursor*) (intptr_t) handle ; + + [mWin setCustomCursor: c]; +} + static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) { NSArray *screens = [NSScreen screens]; if( screen_idx<0 || screen_idx>=[screens count] ) { @@ -632,7 +702,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0 [pool release]; - return (jlong) ((intptr_t) myView); + return (jlong) (intptr_t) myView; } /** @@ -674,7 +744,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow backing: (NSBackingStoreType) bufferingType defer: YES isFullscreenWindow: fullscreen]; - // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]); DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]); diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index ba60b5665..1f907f30e 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -114,6 +114,7 @@ BOOL mouseVisible; BOOL mouseInside; BOOL cursorIsHidden; + NSCursor * customCursor; BOOL realized; BOOL modsDown[4]; // shift, ctrl, alt/option, win/command NSPoint lastInsideMousePosition; @@ -151,7 +152,8 @@ - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; - (BOOL) isMouseInside; -- (void) cursorHide:(BOOL)v; +- (void) cursorHide:(BOOL)v enter:(int)enterState; +- (void) setCustomCursor:(NSCursor*)c; - (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus; - (void) setMouseConfined:(BOOL)v; - (void) setMousePosition:(NSPoint)p; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 4b0198c7e..a7bab9b9d 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -41,6 +41,8 @@ #include +#define PRINTF(...) NSLog(@ __VA_ARGS__) + static jfloat GetDelta(NSEvent *event, jint javaMods[]) { CGEventRef cgEvent = [event CGEvent]; CGFloat deltaY = 0.0; @@ -468,6 +470,7 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { defaultPresentationOptions = 0; fullscreenPresentationOptions = 0; } + isFullscreenWindow = isfs; // Why is this necessary? Without it we don't get any of the // delegate methods like resizing and window movement. @@ -484,6 +487,7 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { mouseVisible = YES; mouseInside = NO; cursorIsHidden = NO; + customCursor = NULL; realized = YES; DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n", res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]); @@ -678,13 +682,36 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n", mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus); if(YES == focus && YES == mouseInside) { - [self cursorHide: !mouseVisible]; + [self cursorHide: !mouseVisible enter: 0]; + } +} + +- (void) setCustomCursor:(NSCursor*)c +{ + if(YES == mouseInside) { + if( NULL != c ) { + DBG_PRINT( "setCustomCursor push: %p\n", c); + [c push]; + } else if( NULL != customCursor && [NSCursor currentCursor] == customCursor ) { + DBG_PRINT( "setCustomCursor pop: %p\n", customCursor); + [customCursor pop]; + } } + customCursor = c; } -- (void) cursorHide:(BOOL)v +- (void) cursorHide:(BOOL)v enter:(int)enterState { - DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v); + DBG_PRINT( "cursorHide: %d -> %d, enter %d\n", cursorIsHidden, v, enterState); + if( NULL != customCursor ) { + if( 1 == enterState && [NSCursor currentCursor] != customCursor ) { + DBG_PRINT( "cursorHide.customCursor push: %p\n", customCursor); + [customCursor push]; + } else if( -1 == enterState && [NSCursor currentCursor] == customCursor ) { + DBG_PRINT( "cursorHide.customCursor pop: %p\n", customCursor); + [customCursor pop]; + } + } if(v) { if(!cursorIsHidden) { [NSCursor hide]; @@ -941,7 +968,7 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "*************** windowDidBecomeKey\n"); mouseInside = [self isMouseInside]; if(YES == mouseInside) { - [self cursorHide: !mouseVisible]; + [self cursorHide: !mouseVisible enter: 0]; } [self focusChanged: YES]; } @@ -995,7 +1022,7 @@ static jint mods2JavaMods(NSUInteger mods) { DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible); mouseInside = YES; - [self cursorHide: !mouseVisible]; + [self cursorHide: !mouseVisible enter: 1]; if(NO == mouseConfined) { [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; } @@ -1006,7 +1033,7 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible); if(NO == mouseConfined) { mouseInside = NO; - [self cursorHide: NO]; + [self cursorHide: NO enter: -1]; [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; } else { [self setMousePosition: lastInsideMousePosition]; @@ -1160,7 +1187,7 @@ static jint mods2JavaMods(NSUInteger mods) jboolean closed = JNI_FALSE; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [self cursorHide: NO]; + [self cursorHide: NO enter: -1]; NSView* nsview = [self contentView]; if( ! [nsview isKindOfClass:[NewtView class]] ) { diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index dd0150e78..2a16dce57 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -139,7 +139,7 @@ #include "NewtCommon.h" -// #define VERBOSE_ON 1 +#define VERBOSE_ON 1 // #define DEBUG_KEYS 1 #ifdef VERBOSE_ON @@ -186,6 +186,10 @@ typedef struct { int height; /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */ int setPointerVisible; + /** Tristate: -1 RESET, 0 NOP, 1 SET-NEW */ + int setPointerAction; + HCURSOR setPointerHandle; + HCURSOR defPointerHandle; /** Bool: 0 NOP, 1 FULLSCREEN */ int setFullscreen; int pointerCaptured; @@ -1023,10 +1027,22 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP } else /* -1 == wud->setPointerVisible */ { visibilityChangeSuccessful = SafeShowCursor(FALSE); } - useDefWindowProc = visibilityChangeSuccessful ? 1 : 0; DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful); wud->setPointerVisible = 0; - // own signal, consumed + // own signal, consumed, no further processing + useDefWindowProc = 0; + res = 1; + } else if( 0 != wud->setPointerAction ) { + if( -1 == wud->setPointerAction ) { + wud->setPointerHandle = wud->defPointerHandle; + } + HCURSOR preHandle = SetCursor(wud->setPointerHandle); + DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested change %d: pre %p -> set %p, def %p\n", + wud->setPointerAction, (void*)preHandle, (void*)wud->setPointerHandle, (void*)wud->defPointerHandle); + wud->setPointerAction = 0; + // own signal, consumed, no further processing + useDefWindowProc = 0; + res = 1; } else { useDefWindowProc = 1; // NOP for us, allow parent to act } @@ -1246,6 +1262,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP if( 0 == wud->pointerInside ) { wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); + SetCursor(wud->setPointerHandle); } (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, @@ -1997,7 +2014,8 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor, - jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags) + jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags, + jlong iconSmallHandle, jlong iconBigHandle) { HWND parentWindow = (HWND) (intptr_t) parent; const TCHAR* wndClassName = NULL; @@ -2054,6 +2072,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo wud->width = width; wud->height = height; wud->setPointerVisible = 0; + wud->setPointerAction = 0; + wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW); + wud->setPointerHandle = wud->defPointerHandle; wud->setFullscreen = 0; wud->pointerCaptured = 0; wud->pointerInside = 0; @@ -2083,6 +2104,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo RECT rc; RECT * insets; + if( 0 != iconSmallHandle ) { + SendMessage(window, WM_SETICON, ICON_SMALL, (LPARAM) iconSmallHandle ); + } + if( 0 != iconBigHandle ) { + SendMessage(window, WM_SETICON, ICON_BIG, (LPARAM) iconBigHandle ); + } ShowWindow(window, SW_SHOW); // send insets before visibility, allowing java code a proper sync point! @@ -2321,3 +2348,83 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0 SetCursorPos(x, y); } +JNIEXPORT jlong JNICALL +Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused, + jobject data, jint data_offset, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) { + + const unsigned char * data_ptr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, data) + data_offset; + const int bytes = 4 * width * height; // BGRA8888 + + DWORD dwWidth, dwHeight; + BITMAPV5HEADER bi; + HBITMAP hBitmap; + void *lpBits; + HICON handle = NULL; + + dwWidth = width; // width of cursor + dwHeight = height; // height of cursor + + ZeroMemory(&bi,sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = dwWidth; + bi.bV5Height = -1 * dwHeight; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + // The following mask specification specifies a supported 32 BPP + // alpha format for Windows XP. + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + HDC hdc; + hdc = GetDC(NULL); + + // Create the DIB section with an alpha channel. + hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, + (void **)&lpBits, NULL, (DWORD)0); + + memcpy(lpBits, data_ptr, bytes); + + ReleaseDC(NULL,hdc); + + // Create an empty mask bitmap. + HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL); + + ICONINFO ii; + ii.fIcon = isCursor ? FALSE : TRUE; + ii.xHotspot = hotX; + ii.yHotspot = hotY; + ii.hbmMask = hMonoBitmap; + ii.hbmColor = hBitmap; + + // Create the alpha cursor with the alpha DIB section. + handle = CreateIconIndirect(&ii); + + DeleteObject(hBitmap); + DeleteObject(hMonoBitmap); + + return (jlong) (intptr_t) handle; +} + +JNIEXPORT void JNICALL +Java_jogamp_newt_driver_windows_DisplayDriver_destroyIcon0(JNIEnv *env, jobject _unused, jlong jhandle) { + HICON handle = (HICON) (intptr_t) jhandle; + DestroyIcon(handle); +} + +JNIEXPORT void JNICALL +Java_jogamp_newt_driver_windows_WindowDriver_setPointerIcon0(JNIEnv *env, jobject _unused, jlong window, jlong iconHandle) { + HWND hwnd = (HWND) (intptr_t) window; + WindowUserData * wud; +#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) + wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA); +#else + wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#endif + wud->setPointerAction = 0 != iconHandle ? 1 : -1; + wud->setPointerHandle = (HCURSOR) (intptr_t) iconHandle; + SendMessage(hwnd, WM_SETCURSOR, 0, 0); +} + diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index e2392a113..19e733111 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -28,6 +28,8 @@ #include "X11Common.h" +#include + // #include // XKB disabled for now jclass X11NewtWindowClazz = NULL; @@ -670,4 +672,54 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } } +/* + * Class: Java_jogamp_newt_driver_x11_DisplayDriver + * Method: createPointerIcon0 + * Signature: (JJILjava/lang/Object;I)V + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0 + (JNIEnv *env, jclass clazz, jlong display, jobject data, jint data_offset, jint width, jint height, jint hotX, jint hotY) +{ + Cursor c; + + if( 0 != data ) { + Display * dpy = (Display *) (intptr_t) display; + char * data_ptr = (char *) (*env)->GetDirectBufferAddress(env, data) + data_offset; + XcursorImage ci; + ci.version = 1; // XCURSOR_IMAGE_VERSION; + ci.size = width; // nominal size (assume square ..) + ci.width = width; + ci.height = height; + ci.xhot = hotX; + ci.yhot = hotY; + ci.delay = 0; + ci.pixels = (XcursorPixel *)(intptr_t)data_ptr; + + c = XcursorImageLoadCursor (dpy, &ci); + + DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", data_ptr, width, height, hotX, hotY, (void *)c); + + } else { + c = 0; + } + return (jlong) (intptr_t) c; +} + +/* + * Class: Java_jogamp_newt_driver_x11_DisplayDriver + * Method: destroyPointerIcon0 + * Signature: (JJILjava/lang/Object;I)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_destroyPointerIcon0 + (JNIEnv *env, jclass clazz, jlong display, jlong handle) +{ + Display * dpy = (Display *) (intptr_t) display; + + if( 0 != handle ) { + Cursor c = (Cursor) (intptr_t) handle; + DBG_PRINT( "X11: destroyPointerIcon0: %p\n", (void *)c); + XFreeCursor(dpy, c); + } +} + diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 5f5dddbe0..da2778004 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -497,6 +497,12 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint } } +static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) { + Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False); + Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False); + XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size); +} + /* * Class: jogamp_newt_driver_x11_WindowDriver * Method: CreateWindow @@ -505,7 +511,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jint visualID, jlong javaObjectAtom, jlong windowDeleteAtom, - jint x, jint y, jint width, jint height, jboolean autoPosition, int flags) + jint x, jint y, jint width, jint height, jboolean autoPosition, int flags, + jint iconDataSize, jobject iconData) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -626,6 +633,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 XEvent event; int left=0, right=0, top=0, bottom=0; + if( 0 < iconDataSize && NULL != iconData ) { + const unsigned char * iconDataPtr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, iconData); + NewtWindows_setIcon(dpy, window, (int)iconDataSize, iconDataPtr); + } + XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values @@ -944,6 +956,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0 #endif } +/* + * Class: Java_jogamp_newt_driver_x11_WindowDriver + * Method: setPointerIcon0 + * Signature: (JJILjava/lang/Object;I)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0 + (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + if( 0 == handle ) { + DBG_PRINT( "X11: setPointerIcon0: reset\n"); + XUndefineCursor(dpy, w); + } else { + Cursor c = (Cursor) (intptr_t) handle; + DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c); + XDefineCursor(dpy, w, c); + } +} + /* * Class: Java_jogamp_newt_driver_x11_WindowDriver * Method: setPointerVisible0 diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index b54a2cd19..efec961de 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -30,7 +30,9 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; import java.io.IOException; +import com.jogamp.common.util.IOUtil; import com.jogamp.newt.Display; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.event.KeyAdapter; @@ -44,9 +46,7 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; - import com.jogamp.opengl.util.Animator; - import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import javax.media.nativewindow.NativeWindowFactory; @@ -54,7 +54,6 @@ import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.DimensionImmutable; - import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -171,6 +170,20 @@ public class TestGearsES2NEWT extends UITestCase { } }); + final PointerIcon pointerIconOne; + { + PointerIcon _pointerIconOne = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + final Display disp = glWindow.getScreen().getDisplay(); + disp.createNative(); + try { + _pointerIconOne = disp.createPointerIcon(res, 32, 0); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIconOne = _pointerIconOne; + } + glWindow.addKeyListener(new KeyAdapter() { @Override public void keyPressed(final KeyEvent e) { @@ -203,6 +216,16 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); } }.start(); + } else if(e.getKeyChar()=='c') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + glWindow.setPointerIcon( currentPI == pointerIconOne ? null : pointerIconOne); + System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); + glWindow.setExclusiveContextThread(t); + } }.start(); } else if(e.getKeyChar()=='d') { new Thread() { public void run() { -- cgit v1.2.3 From 6569b352a982654a17b9b04b2bc3b3dca8d7448d Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 2 Jan 2014 20:23:28 +0100 Subject: MacWindow.m: Add missing NSAutoreleasePool 'decoration' --- src/newt/native/MacWindow.m | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 16e9814ef..8a466b95e 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -319,40 +319,48 @@ static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jico JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0 (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); if( NULL != nsImage ) { [nsImage autorelease]; [NSApp setApplicationIconImage: nsImage]; } + [pool release]; } JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0 (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight, jint hotX, jint hotY) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); + NSCursor * res = NULL; if( NULL != nsImage ) { [nsImage autorelease]; NSPoint hotP = { hotX, hotY }; - NSCursor * c = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; - return (jlong) (intptr_t) c; + res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; } - return 0; + [pool release]; + return (jlong) (intptr_t) res; } JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0 (JNIEnv *env, jobject unused, jlong handle) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSCursor * c = (NSCursor*) (intptr_t) handle ; [c release]; + [pool release]; } JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 (JNIEnv *env, jobject unused, jlong window, jlong handle) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; NSCursor * c = (NSCursor*) (intptr_t) handle ; [mWin setCustomCursor: c]; + [pool release]; } static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) { @@ -1332,9 +1340,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; + [pool release]; return JNI_TRUE; } @@ -1346,8 +1356,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; + [pool release]; return JNI_TRUE; } @@ -1359,7 +1371,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePo JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); [mWin setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; + [pool release]; } -- cgit v1.2.3 From bb5c7496ed92b91dded30816a46b42ff85f37bec Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 3 Jan 2014 04:29:38 +0100 Subject: Bug 935: NEWT PointerIcon OSX: Safe use of NSCursor handle --- src/newt/native/MacWindow.m | 17 ++++++++++++++--- src/newt/native/NewtMacWindow.h | 4 ++-- src/newt/native/NewtMacWindow.m | 37 ++++++++++++++++++++++++++----------- 3 files changed, 42 insertions(+), 16 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 8a466b95e..1be3a6ed5 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -340,6 +340,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPoint res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; } [pool release]; + DBG_PRINT( "createPointerIcon0 %p\n", res); return (jlong) (intptr_t) res; } @@ -348,7 +349,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPoint { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSCursor * c = (NSCursor*) (intptr_t) handle ; - [c release]; + if( NULL != c ) { + if ( NO == [c isKindOfClass:[NSCursor class]] ) { + DBG_PRINT( "destroyPointerIcon0 NSCursor %p - is of invalid type\n", c); + } else { + DBG_PRINT( "destroyPointerIcon0 %p\n", c); + [c release]; + } + } [pool release]; } @@ -358,8 +366,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIco NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; NSCursor * c = (NSCursor*) (intptr_t) handle ; - - [mWin setCustomCursor: c]; + if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { + DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (1)\n", c); + } else { + [mWin setPointerIcon: c]; + } [pool release]; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index ba2e242cf..2728c2201 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -41,7 +41,7 @@ // #define VERBOSE_ON 1 #ifdef VERBOSE_ON - #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) + #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr) // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) #else #define DBG_PRINT(...) @@ -151,7 +151,7 @@ - (BOOL) isMouseInside; - (void) cursorHide:(BOOL)v enter:(int)enterState; -- (void) setCustomCursor:(NSCursor*)c; +- (void) setPointerIcon:(NSCursor*)c; - (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus; - (void) setMouseConfined:(BOOL)v; - (void) setMousePosition:(NSPoint)p; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 9f534e319..96965b67a 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -670,15 +670,23 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { } } -- (void) setCustomCursor:(NSCursor*)c +- (void) setPointerIcon:(NSCursor*)c { + DBG_PRINT( "setPointerIcon: mouseInside cursor: %p -> %p (glob %p), mouseInside %d\n", customCursor, c, [NSCursor currentCursor], (int)mouseInside); if(YES == mouseInside) { if( NULL != c ) { - DBG_PRINT( "setCustomCursor push: %p\n", c); + DBG_PRINT( "setPointerIcon push: %p\n", c); [c push]; - } else if( NULL != customCursor && [NSCursor currentCursor] == customCursor ) { - DBG_PRINT( "setCustomCursor pop: %p\n", customCursor); - [customCursor pop]; + } else if( NULL != customCursor ) { + if ( NO == [customCursor isKindOfClass:[NSCursor class]] ) { + DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (2)\n", customCursor); + if( [NSCursor currentCursor] == customCursor ) { + [NSCursor pop]; + } + } else if( [NSCursor currentCursor] == customCursor ) { + DBG_PRINT( "setPointerIcon pop: %p\n", customCursor); + [customCursor pop]; + } } } customCursor = c; @@ -688,12 +696,19 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { { DBG_PRINT( "cursorHide: %d -> %d, enter %d\n", cursorIsHidden, v, enterState); if( NULL != customCursor ) { - if( 1 == enterState && [NSCursor currentCursor] != customCursor ) { - DBG_PRINT( "cursorHide.customCursor push: %p\n", customCursor); - [customCursor push]; - } else if( -1 == enterState && [NSCursor currentCursor] == customCursor ) { - DBG_PRINT( "cursorHide.customCursor pop: %p\n", customCursor); - [customCursor pop]; + if ( NO == [customCursor isKindOfClass:[NSCursor class]] ) { + DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (3)\n", customCursor); + if( [NSCursor currentCursor] == customCursor ) { + [NSCursor pop]; + } + } else { + if( 1 == enterState && [NSCursor currentCursor] != customCursor ) { + DBG_PRINT( "cursorHide.PointerIcon push: %p\n", customCursor); + [customCursor push]; + } else if( -1 == enterState && [NSCursor currentCursor] == customCursor ) { + DBG_PRINT( "cursorHide.PointerIcon pop: %p\n", customCursor); + [customCursor pop]; + } } } if(v) { -- cgit v1.2.3 From fcc0e7397bb6f3ceb1fe143667f8c59b5bf63874 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 4 Jan 2014 17:15:04 +0100 Subject: Bug 935: NEWT PointerIcon: Refine Spec and Implementation / Fix OSX Crash and Issues - Refine Display.PointerIcon: Complete type allowing re-creation - Add associated Display reference - Add used IOUtil.ClassResources reference - Add isValid()/validate() methods for recreation - Refine API doc - Move Display.destroyPointerIcon(PointerIcon) -> PointerIcon.destroy() - Move DisplayImpl.PointerIconImpl -> PointerIconImpl (own source file) - Creation/Destruction and setting of PointerIcon happens on EDT - DisplayImpl.shutdownAll() and Display.destroy() calls destroyAllPointerIconFromList - WindowDriver.setPointerIconImpl: Validates PointerIconImpl (i.e. re-creates if required) - Fix 'initial' window.setPointerIcon(..) before createNative(..), tested w/ TestGearsES2NEWT - OSX Native Code: - Move mouse and pointer-state handling from NewtMacWindow -> NewtView class to retain states (pointer handle, pointer visibility, etc) when reparenting. Reparenting will move an exisiting NewtView into a new NewtMacWindow. - Enable all mouse move events: - NewtView::mouseEnter [nsWin makeFirstResponder: nsView]; - NewtView::mouseExited if( !mouseConfined ) { [nsView resignFirstResponder]; } - NewtView::mouseMoved issued [myCurser set] if required, fixing OSX issue not updating NSCursor properly. - MacWindow: - Test NewtMacWindow, NewtView and NSCursor handles before usage - Fix DBG_PRINT(..) warnings --- make/scripts/tests-win.bat | 4 +- make/scripts/tests.sh | 4 +- src/newt/classes/com/jogamp/newt/Display.java | 67 +- src/newt/classes/jogamp/newt/DisplayImpl.java | 91 +- src/newt/classes/jogamp/newt/PointerIconImpl.java | 126 ++ src/newt/classes/jogamp/newt/WindowImpl.java | 9 +- .../jogamp/newt/driver/macosx/DisplayDriver.java | 11 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 34 +- .../jogamp/newt/driver/windows/DisplayDriver.java | 11 +- .../jogamp/newt/driver/windows/WindowDriver.java | 4 +- .../jogamp/newt/driver/x11/DisplayDriver.java | 22 +- .../jogamp/newt/driver/x11/WindowDriver.java | 14 +- src/newt/native/MacWindow.m | 113 +- src/newt/native/NewtMacWindow.h | 86 +- src/newt/native/NewtMacWindow.m | 1237 ++++++++++---------- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 28 +- .../parenting/NewtAWTReparentingKeyAdapter.java | 53 +- 17 files changed, 1106 insertions(+), 808 deletions(-) create mode 100644 src/newt/classes/jogamp/newt/PointerIconImpl.java (limited to 'src/newt/native/MacWindow.m') diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat index d95b0025f..1158abdbb 100755 --- a/make/scripts/tests-win.bat +++ b/make/scripts/tests-win.bat @@ -6,14 +6,14 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersion REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.DemoGLJPanelPerf02AWT %* -REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT %* +scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 4c084d705..db852ce42 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -323,9 +323,9 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $* -#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* +testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NEWT $* #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $* diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index cf1099c85..8d1445f80 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -66,16 +66,60 @@ public abstract class Display { /** * Native PointerIcon handle. *

    - * Instances can be created via {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int)} - * and released via {@link Display#destroyPointerIcon(PointerIcon)}. + * Instances can be created via {@link Display}'s {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(..)}. + *

    + *

    + * Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed. + *

    + *

    + * Instance can be re-validated after destruction via {@link #validate()}. + *

    + *

    + * {@link PointerIcon} may be {@link #destroy() destroyed} manually after use, + * i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore. *

    *

    * PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}. *

    */ public static interface PointerIcon { + /** + * @return the associated Display + */ + Display getDisplay(); + + /** + * @return the single {@link IOUtil.ClassResources}. + */ + IOUtil.ClassResources getResource(); + + /** + * Returns true if valid, otherwise false. + *

    + * A PointerIcon instance becomes invalid if it's {@link #getDisplay() associated Display} is destroyed. + *

    + */ + boolean isValid(); + + /** + * Returns true if instance {@link #isValid()} or validation was successful, otherwise false. + *

    + * Validation, i.e. recreation, is required if instance became invalid, see {@link #isValid()}. + *

    + */ + boolean validate(); + + /** + * Destroys this instance. + *

    + * Will be called automatically if it's {@link #getDisplay() associated Display} is destroyed. + *

    + */ + void destroy(); + /** Returns the size, i.e. width and height. */ DimensionImmutable getSize(); + /** Returns the hotspot. */ PointImmutable getHotspot(); @@ -84,28 +128,23 @@ public abstract class Display { } /** - * Returns the created {@link PointerIcon} or null if not implemented on platform. + * Returns the newly created {@link PointerIcon} or null if not implemented on platform. + *

    + * See {@link PointerIcon} for lifecycle semantics. + *

    * - * @param pngResource PNG resource + * @param pngResource single PNG resource, only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used. * @param hotX pointer hotspot x-coord, origin is upper-left corner * @param hotY pointer hotspot y-coord, origin is upper-left corner + * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}. * @throws MalformedURLException * @throws InterruptedException * @throws IOException * * @see PointerIcon - * @see #destroyPointerIcon(PointerIcon) * @see Window#setPointerIcon(PointerIcon) */ - - public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException; - - /** - * @param pi - * - * @see #createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) - */ - public abstract void destroyPointerIcon(PointerIcon pi); + public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws IllegalStateException, MalformedURLException, InterruptedException, IOException; /** * Manual trigger the native creation, if it is not done yet.
    diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index dc3705daa..346c03b15 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -51,8 +51,6 @@ import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.PointImmutable; public abstract class DisplayImpl extends Display { private static int serialno = 1; @@ -68,49 +66,19 @@ public abstract class DisplayImpl extends Display { }); } - public static class PointerIconImpl implements PointerIcon { - public final long handle; - private final DimensionImmutable size; - private final PointImmutable hotspot; - public PointerIconImpl(final long handle, final DimensionImmutable size, final PointImmutable hotspot) { - this.handle=handle; - this.size = size; - this.hotspot = hotspot; - } - @Override - public final DimensionImmutable getSize() { - return size; - } - @Override - public final PointImmutable getHotspot() { - return hotspot; - } - @Override - public final String toString() { - return "PointerIcon[0x"+Long.toHexString(handle)+", "+size+", "+hotspot+"]"; - } - } - - private void addPointerIconToList(final PointerIcon pi) { - synchronized(pointerIconList) { - pointerIconList.add(pi); - } - } - private void delPointerIconFromList(final PointerIcon pi) { - synchronized(pointerIconList) { - pointerIconList.remove(pi); - } - } - private final ArrayList pointerIconList = new ArrayList(); + final ArrayList pointerIconList = new ArrayList(); /** Executed from EDT! */ private void destroyAllPointerIconFromList(final long dpy) { synchronized(pointerIconList) { - for( int i=0; i < pointerIconList.size(); i++ ) { - final PointerIcon item = pointerIconList.get(i); - if( null != item ) { - // destroy! - destroyPointerIconImpl(dpy, item); + final int count = pointerIconList.size(); + for( int i=0; i < count; i++ ) { + final PointerIconImpl item = pointerIconList.get(i); + if(DEBUG) { + System.err.println("destroyAllPointerIconFromList: dpy "+toHexString(dpy)+", # "+i+"/"+count+": "+item+" @ "+getThreadName()); + } + if( null != item && item.isValid() ) { + item.destroyOnEDT(dpy); } } pointerIconList.clear(); @@ -119,31 +87,37 @@ public abstract class DisplayImpl extends Display { @Override public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { - final PointerIcon res = createPointerIconImpl(pngResource, hotX, hotY); - addPointerIconToList(res); - return res; - } - protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { - return null; + return createPointerIcon(false /* isTemp */, pngResource, hotX, hotY); } - - @Override - public final void destroyPointerIcon(final PointerIcon pi) { - delPointerIconFromList(pi); - runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - @Override - public Object run(long dpy) { + PointerIcon createPointerIcon(final boolean isTemp, final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + if( !isNativeValid() ) { + throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this); + } + final PointerIconImpl[] res = { null }; + runOnEDTIfAvail(true, new Runnable() { + public void run() { try { - destroyPointerIconImpl(dpy, pi); + if( !DisplayImpl.this.isNativeValid() ) { + throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this); + } + res[0] = createPointerIconImpl(pngResource, hotX, hotY); } catch (Exception e) { e.printStackTrace(); } - return null; + } } ); + if( !isTemp ) { + synchronized(pointerIconList) { + pointerIconList.add(res[0]); } - }); + } + return res[0]; + } + /** Executed from EDT! */ + protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + return null; } /** Executed from EDT! */ - protected void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { } + protected void destroyPointerIconImpl(final long displayHandle, long piHandle) { } /** Ensure static init has been run. */ /* pp */static void initSingleton() { } @@ -399,6 +373,7 @@ public abstract class DisplayImpl extends Display { @Override public void run() { if ( null != d.getGraphicsDevice() ) { + d.destroyAllPointerIconFromList(f_aDevice.getHandle()); d.closeNativeImpl(f_aDevice); } } diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java new file mode 100644 index 000000000..e2388be67 --- /dev/null +++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java @@ -0,0 +1,126 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.newt; + +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PointImmutable; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.IOUtil.ClassResources; +import com.jogamp.newt.Display; +import com.jogamp.newt.Display.PointerIcon; + +public class PointerIconImpl implements PointerIcon { + private final DisplayImpl display; + private final IOUtil.ClassResources resource; + private final DimensionImmutable size; + private final PointImmutable hotspot; + private long handle; + public PointerIconImpl(DisplayImpl display, ClassResources resource, final DimensionImmutable size, final PointImmutable hotspot, final long handle) { + this.display = display; + this.resource = resource; + this.size = size; + this.hotspot = hotspot; + this.handle=handle; + } + public synchronized final long getHandle() { return handle; } + public synchronized final long validatedHandle() { + synchronized(display.pointerIconList) { + if( !display.pointerIconList.contains(this) ) { + display.pointerIconList.add(this); + } + } + if( 0 == handle ) { + try { + final PointerIconImpl temp = (PointerIconImpl) display.createPointerIcon(true /* isTemp */, resource, hotspot.getX(), hotspot.getY()); + handle = temp.handle; + return handle; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } else { + return handle; + } + } + @Override + public final Display getDisplay() { return display; } + @Override + public final IOUtil.ClassResources getResource() { return resource; } + @Override + public synchronized final boolean isValid() { return 0 != handle; } + @Override + public synchronized final boolean validate() { + if( 0 == handle ) { + return 0 != validatedHandle(); + } + return true; + } + + @Override + public synchronized void destroy() { + if(DisplayImpl.DEBUG) { + System.err.println("PointerIcon.destroy: "+this+", "+display+", "+DisplayImpl.getThreadName()); + } + if( 0 != handle ) { + synchronized(display.pointerIconList) { + display.pointerIconList.remove(this); + } + display.runOnEDTIfAvail(false, new Runnable() { + public void run() { + if( display.isNativeValid() ) { + destroyOnEDT(display.getHandle()); + } + } } ); + } + } + + /** No checks, assume execution on EDT */ + synchronized void destroyOnEDT(final long dpy) { + final long h = handle; + handle = 0; + try { + display.destroyPointerIconImpl(dpy, h); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public final DimensionImmutable getSize() { + return size; + } + @Override + public final PointImmutable getHotspot() { + return hotspot; + } + @Override + public final String toString() { + return "PointerIcon["+DisplayImpl.toHexString(super.hashCode())+", "+display.getFQName()+", "+resource.resourcePaths[0]+", 0x"+Long.toHexString(handle)+", "+size+", "+hotspot+"]"; + } +} \ No newline at end of file diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index d078caa3b..8d9fb8d7e 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -84,7 +84,6 @@ import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; import jogamp.nativewindow.SurfaceUpdatedHelper; -import jogamp.newt.DisplayImpl.PointerIconImpl; public abstract class WindowImpl implements Window, NEWTEventConsumer { @@ -440,7 +439,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer screen.addMonitorModeListener(monitorModeListenerImpl); setTitleImpl(title); if( null != pointerIcon ) { - setPointerIcon(pointerIcon); + setPointerIconImpl((PointerIconImpl)pointerIcon); } setPointerVisibleImpl(pointerVisible); confinePointerImpl(pointerConfined); @@ -1689,9 +1688,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final void setPointerIcon(final PointerIcon pi) { if( this.pointerIcon != pi ) { - setPointerIcon(pointerIcon); if( isNativeValid() ) { - setPointerIconImpl((PointerIconImpl)pi); + runOnEDTIfAvail(true, new Runnable() { + public void run() { + setPointerIconImpl((PointerIconImpl)pi); + } } ); } this.pointerIcon = pi; } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java index f0f0a955a..30583c48c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -50,6 +50,7 @@ import com.jogamp.newt.NewtFactory; import jogamp.newt.DisplayImpl; import jogamp.newt.NEWTJNILibLoader; +import jogamp.newt.PointerIconImpl; import jogamp.newt.driver.PNGIcon; public class DisplayDriver extends DisplayImpl { @@ -112,21 +113,21 @@ public class DisplayDriver extends DisplayImpl { } @Override - protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { if( PNGIcon.isAvailable() ) { final int[] width = { 0 }, height = { 0 }, data_size = { 0 }; if( null != pngResource && 0 < pngResource.resourceCount() ) { - return new PointerIconImpl( createPointerIcon0(data, width[0], height[0], hotX, hotY), - new Dimension(width[0], height[0]), new Point(hotX, hotY)); final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size); + return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]), + new Point(hotX, hotY), createPointerIcon0(data, width[0], height[0], hotX, hotY)); } } return null; } @Override - protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { - destroyPointerIcon0(((PointerIconImpl)pi).handle); + protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) { + destroyPointerIcon0(piHandle); } public static void runNSApplication() { diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index a55fa915a..6f3c95570 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -45,8 +45,8 @@ import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.newt.PointerIconImpl; import jogamp.newt.WindowImpl; -import jogamp.newt.DisplayImpl.PointerIconImpl; import jogamp.newt.driver.DriverClearFocus; import jogamp.newt.driver.DriverUpdatePosition; @@ -394,17 +394,29 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected void setPointerIconImpl(final PointerIconImpl pi) { - OSXUtil.RunOnMainThread(false, new Runnable() { - @Override - public void run() { - setPointerIcon0(getWindowHandle(), null != pi ? pi.handle : 0); - } } ); + if( !isOffscreenInstance ) { + final long piHandle = null != pi ? pi.validatedHandle() : 0; + OSXUtil.RunOnMainThread(true, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle ! + @Override + public void run() { + if( !setPointerIcon0(getWindowHandle(), piHandle) ) { + throw new RuntimeException("Failed: "+pi+", "+WindowDriver.this); + } + } } ); + } // else may need offscreen solution ? FIXME } @Override protected boolean setPointerVisibleImpl(final boolean pointerVisible) { if( !isOffscreenInstance ) { - return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible); + OSXUtil.RunOnMainThread(false, new Runnable() { + @Override + public void run() { + if( !setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible) ) { + throw new RuntimeException("Failed"); + } + } } ); + return true; // setPointerVisible0 always returns true .. } // else may need offscreen solution ? FIXME return false; } @@ -420,7 +432,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected void warpPointerImpl(final int x, final int y) { if( !isOffscreenInstance ) { - warpPointer0(getWindowHandle(), x, y); + if( !warpPointer0(getWindowHandle(), x, y) ) { + throw new RuntimeException("Failed"); + } } // else may need offscreen solution ? FIXME } @@ -575,10 +589,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Must be called on Main-Thread */ private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); + private static native boolean setPointerIcon0(long windowHandle, long handle); private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); private static native boolean confinePointer0(long windowHandle, boolean confine); - private static native void warpPointer0(long windowHandle, int x, int y); - private static native void setPointerIcon0(long windowHandle, long handle); + private static native boolean warpPointer0(long windowHandle, int x, int y); // Window styles private static final int NSBorderlessWindowMask = 0; diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java index 39b2efd15..1e9c78a5d 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java @@ -43,6 +43,7 @@ import jogamp.nativewindow.windows.RegisteredClass; import jogamp.nativewindow.windows.RegisteredClassFactory; import jogamp.newt.DisplayImpl; import jogamp.newt.NEWTJNILibLoader; +import jogamp.newt.PointerIconImpl; import jogamp.newt.driver.PNGIcon; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -104,21 +105,21 @@ public class DisplayDriver extends DisplayImpl { } @Override - protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { if( PNGIcon.isAvailable() ) { final int[] width = { 0 }, height = { 0 }, data_size = { 0 }; if( null != pngResource && 0 < pngResource.resourceCount() ) { - return new PointerIconImpl( createBGRA8888Icon0(data, width[0], height[0], true, hotX, hotY), - new Dimension(width[0], height[0]), new Point(hotX, hotY)); final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size); + return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]), + new Point(hotX, hotY), createBGRA8888Icon0(data, width[0], height[0], true, hotX, hotY)); } } return null; } @Override - protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { - destroyIcon0(((PointerIconImpl)pi).handle); + protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) { + destroyIcon0(piHandle); } //---------------------------------------------------------------------- diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java index 764d4fdab..c8d7c65cc 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -38,8 +38,8 @@ import java.nio.ByteBuffer; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.GDIUtil; +import jogamp.newt.PointerIconImpl; import jogamp.newt.WindowImpl; -import jogamp.newt.DisplayImpl.PointerIconImpl; import jogamp.newt.driver.PNGIcon; import javax.media.nativewindow.AbstractGraphicsConfiguration; @@ -252,7 +252,7 @@ public class WindowDriver extends WindowImpl { @Override protected void setPointerIconImpl(final PointerIconImpl pi) { - setPointerIcon0(getWindowHandle(), null != pi ? pi.handle : 0); + setPointerIcon0(getWindowHandle(), null != pi ? pi.validatedHandle() : 0); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java index c377e7f85..150337df4 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java @@ -51,6 +51,7 @@ import com.jogamp.nativewindow.x11.X11GraphicsDevice; import jogamp.nativewindow.x11.X11Util; import jogamp.newt.DisplayImpl; import jogamp.newt.NEWTJNILibLoader; +import jogamp.newt.PointerIconImpl; import jogamp.newt.driver.PNGIcon; public class DisplayDriver extends DisplayImpl { @@ -131,32 +132,21 @@ public class DisplayDriver extends DisplayImpl { protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; } @Override - protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { if( PNGIcon.isAvailable() ) { final int[] width = { 0 }, height = { 0 }, data_size = { 0 }; if( null != pngResource && 0 < pngResource.resourceCount() ) { final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, false /* toBGRA */, width, height, data_size); - final long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { - @Override - public Long run(long dpy) { - long h = 0; - try { - h = createPointerIcon0(dpy, data, width[0], height[0], hotX, hotY); - } catch (Exception e) { - e.printStackTrace(); - } - return Long.valueOf(h); - } - }).longValue(); - return new PointerIconImpl(handle, new Dimension(width[0], height[0]), new Point(hotX, hotY)); + final long handle = createPointerIcon0(getHandle(), data, width[0], height[0], hotX, hotY); + return new PointerIconImpl(DisplayDriver.this, pngResource, new Dimension(width[0], height[0]), new Point(hotX, hotY), handle); } } return null; } @Override - protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { - destroyPointerIcon0(displayHandle, ((PointerIconImpl)pi).handle); + protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) { + destroyPointerIcon0(displayHandle, piHandle); } //---------------------------------------------------------------------- diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index 0ea2c5358..ad1744f2e 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -40,7 +40,7 @@ import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; import jogamp.newt.DisplayImpl; import jogamp.newt.DisplayImpl.DisplayRunnable; -import jogamp.newt.DisplayImpl.PointerIconImpl; +import jogamp.newt.PointerIconImpl; import jogamp.newt.WindowImpl; import jogamp.newt.driver.PNGIcon; @@ -279,7 +279,7 @@ public class WindowDriver extends WindowImpl { @Override public Object run(long dpy) { try { - setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.handle : 0); + setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.validatedHandle() : 0); } catch (Exception e) { e.printStackTrace(); } @@ -293,7 +293,15 @@ public class WindowDriver extends WindowImpl { return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { @Override public Boolean run(long dpy) { - return Boolean.valueOf(setPointerVisible0(dpy, getWindowHandle(), pointerVisible)); + final PointerIconImpl pi = (PointerIconImpl)getPointerIcon(); + final boolean res; + if( pointerVisible && null != pi ) { + setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.validatedHandle() : 0); + res = true; + } else { + res = setPointerVisible0(dpy, getWindowHandle(), pointerVisible); + } + return Boolean.valueOf(res); } }).booleanValue(); } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 1be3a6ed5..eb5913706 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -347,30 +347,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPoint JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0 (JNIEnv *env, jobject unused, jlong handle) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSCursor * c = (NSCursor*) (intptr_t) handle ; - if( NULL != c ) { - if ( NO == [c isKindOfClass:[NSCursor class]] ) { - DBG_PRINT( "destroyPointerIcon0 NSCursor %p - is of invalid type\n", c); - } else { - DBG_PRINT( "destroyPointerIcon0 %p\n", c); - [c release]; - } + if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { + DBG_PRINT( "Not a NSCursor %p\n", c); + return; } - [pool release]; -} - -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 - (JNIEnv *env, jobject unused, jlong window, jlong handle) -{ + DBG_PRINT( "destroyPointerIcon0 %p\n", c); NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; - NSCursor * c = (NSCursor*) (intptr_t) handle ; - if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { - DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (1)\n", c); - } else { - [mWin setPointerIcon: c]; - } + [c release]; [pool release]; } @@ -717,7 +701,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0 NSRect rectView = NSMakeRect(0, 0, w, h); NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ; - DBG_PRINT( "createView0.X.%d - new view: %p\n", myView); + DBG_PRINT( "createView0.X - new view: %p\n", myView); [pool release]; @@ -738,7 +722,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* myView = (NewtView*) (intptr_t) jview ; - DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n", + DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n", (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, (int)styleMask, (int)bufferingType, myView); (void)myView; @@ -865,6 +849,7 @@ NS_ENDHANDLER // Set the content view changeContentView(env, jthis, parentView, myWindow, myView, NO); + [myWindow setInitialFirstResponder: myView]; DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); @@ -965,7 +950,6 @@ NS_ENDHANDLER JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 (JNIEnv *env, jobject unused, jlong window) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n"); @@ -979,6 +963,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 DBG_PRINT( "windowClose.0 - Not a NEWT win - abort\n"); return; } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* mView = (NewtView *)[mWin contentView]; BOOL fullscreen = mWin->isFullscreenWindow; BOOL destroyNotifySent, isNSView, isNewtView; @@ -1093,6 +1078,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 #endif DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); + [mWin setAcceptsMouseMovedEvents: YES]; [mWin makeFirstResponder: nil]; [mWin orderFrontRegardless]; [mWin makeKeyWindow]; @@ -1331,18 +1317,39 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) { NSObject *nsObj = (NSObject*) ((intptr_t) win); - NewtMacWindow * mWin = NULL; - - if( [nsObj isKindOfClass:[NewtMacWindow class]] ) { - mWin = (NewtMacWindow*) nsObj; - } else { - NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj); + NewtMacWindow * mWin = (NewtMacWindow*) nsObj; + if( ![mWin isKindOfClass:[NewtMacWindow class]] ) { + DBG_PRINT("Not a NewtMacWindow %p\n", nsObj); + return NULL; } - NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)]; return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y); } +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 + (JNIEnv *env, jobject unused, jlong window, jlong handle) +{ + NSCursor *c = (NSCursor*) (intptr_t) handle ; + if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { + DBG_PRINT("Not a NSCursor %p\n", c); + return JNI_FALSE; + } + NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; + if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { + DBG_PRINT("Not a NewtMacWindow %p\n", mWin); + return JNI_FALSE; + } + NewtView* nView = (NewtView *) [mWin contentView]; + if( ! [nView isKindOfClass:[NewtView class]] ) { + DBG_PRINT("Not a NewtView %p\n", nView); + return JNI_FALSE; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [nView setPointerIcon: c]; + [pool release]; + return JNI_TRUE; +} + /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: setPointerVisible0 @@ -1351,10 +1358,19 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO - hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; + if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { + DBG_PRINT("Not a NewtMacWindow %p\n", mWin); + return JNI_FALSE; + } + NewtView* nView = (NewtView *) [mWin contentView]; + if( ! [nView isKindOfClass:[NewtView class]] ) { + DBG_PRINT("Not a NewtView %p\n", nView); + return JNI_FALSE; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO + hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; [pool release]; return JNI_TRUE; } @@ -1367,9 +1383,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; + if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { + DBG_PRINT("Not a NewtMacWindow %p\n", mWin); + return JNI_FALSE; + } + NewtView* nView = (NewtView *) [mWin contentView]; + if( ! [nView isKindOfClass:[NewtView class]] ) { + DBG_PRINT("Not a NewtView %p\n", nView); + return JNI_FALSE; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; [pool release]; return JNI_TRUE; } @@ -1379,12 +1404,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePo * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); - [mWin setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; + if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { + DBG_PRINT("Not a NewtMacWindow %p\n", mWin); + return JNI_FALSE; + } + NewtView* nView = (NewtView *) [mWin contentView]; + if( ! [nView isKindOfClass:[NewtView class]] ) { + DBG_PRINT("Not a NewtView %p\n", nView); + return JNI_FALSE; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; [pool release]; + return JNI_TRUE; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 2728c2201..daf75bec7 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -63,6 +63,14 @@ volatile NSTrackingRectTag ptrTrackingTag; NSRect ptrRect; + NSCursor * myCursor; + BOOL modsDown[4]; // shift, ctrl, alt/option, win/command + + BOOL mouseConfined; + BOOL mouseInside; + BOOL mouseVisible; + BOOL cursorIsHidden; + NSPoint lastInsideMousePosition; } - (id)initWithFrame:(NSRect)frameRect; @@ -83,9 +91,6 @@ - (void) setJavaWindowObject: (jobject) javaWindowObj; - (jobject) getJavaWindowObject; -- (void) rightMouseDown: (NSEvent*) theEvent; -- (void) resetCursorRects; - - (void) setDestroyNotifySent: (BOOL) v; - (BOOL) getDestroyNotifySent; @@ -99,6 +104,41 @@ - (void) viewDidHide; - (void) viewDidUnhide; - (BOOL) acceptsFirstResponder; +- (BOOL) becomeFirstResponder; +- (BOOL) resignFirstResponder; + +- (void) removeCursorRects; +- (void) addCursorRects; +- (void) removeMyCursor; +- (void) resetCursorRects; +- (void) setPointerIcon: (NSCursor*)c; +- (void) mouseEntered: (NSEvent*) theEvent; +- (void) mouseExited: (NSEvent*) theEvent; +- (BOOL) updateMouseInside; +- (void) cursorHide:(BOOL)v enter:(int)enterState; +- (void) setPointerIcon:(NSCursor*)c; +- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus; +- (BOOL) isMouseVisible; +- (void) setMouseConfined:(BOOL)v; +- (void) setMousePosition:(NSPoint)p; +- (void) mouseMoved: (NSEvent*) theEvent; +- (void) scrollWheel: (NSEvent*) theEvent; +- (void) mouseDown: (NSEvent*) theEvent; +- (void) mouseDragged: (NSEvent*) theEvent; +- (void) mouseUp: (NSEvent*) theEvent; +- (void) rightMouseDown: (NSEvent*) theEvent; +- (void) rightMouseDragged: (NSEvent*) theEvent; +- (void) rightMouseUp: (NSEvent*) theEvent; +- (void) otherMouseDown: (NSEvent*) theEvent; +- (void) otherMouseDragged: (NSEvent*) theEvent; +- (void) otherMouseUp: (NSEvent*) theEvent; +- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType; +- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; + +- (void) handleFlagsChanged:(NSUInteger) mods; +- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods; +- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType; +- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType; @end @@ -108,14 +148,7 @@ @interface NewtMacWindow : NSWindow #endif { - BOOL mouseConfined; - BOOL mouseVisible; - BOOL mouseInside; - BOOL cursorIsHidden; - NSCursor * customCursor; BOOL realized; - BOOL modsDown[4]; // shift, ctrl, alt/option, win/command - NSPoint lastInsideMousePosition; @public BOOL hasPresentationSwitch; NSUInteger defaultPresentationOptions; @@ -147,20 +180,14 @@ - (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p; - (NSSize) newtClientSize2TLSize: (NSSize) nsz; - (NSPoint) getLocationOnScreen: (NSPoint) p; -- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; -- (BOOL) isMouseInside; -- (void) cursorHide:(BOOL)v enter:(int)enterState; -- (void) setPointerIcon:(NSCursor*)c; -- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus; -- (void) setMouseConfined:(BOOL)v; -- (void) setMousePosition:(NSPoint)p; - -- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType; -- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType; -- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType; - (void) focusChanged: (BOOL) gained; +- (void) keyDown: (NSEvent*) theEvent; +- (void) keyUp: (NSEvent*) theEvent; +- (void) flagsChanged: (NSEvent *) theEvent; +- (BOOL) acceptsMouseMovedEvents; +- (BOOL) acceptsFirstResponder; - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; - (BOOL) canBecomeKeyWindow; @@ -168,22 +195,7 @@ - (void) resignKeyWindow; - (void) windowDidBecomeKey: (NSNotification *) notification; - (void) windowDidResignKey: (NSNotification *) notification; -- (void) keyDown: (NSEvent*) theEvent; -- (void) keyUp: (NSEvent*) theEvent; -- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods; -- (void) flagsChanged: (NSEvent *) theEvent; -- (void) mouseEntered: (NSEvent*) theEvent; -- (void) mouseExited: (NSEvent*) theEvent; -- (void) mouseMoved: (NSEvent*) theEvent; -- (void) scrollWheel: (NSEvent*) theEvent; -- (void) mouseDown: (NSEvent*) theEvent; -- (void) mouseDragged: (NSEvent*) theEvent; -- (void) mouseUp: (NSEvent*) theEvent; -- (void) rightMouseDown: (NSEvent*) theEvent; -- (void) rightMouseDragged: (NSEvent*) theEvent; -- (void) rightMouseUp: (NSEvent*) theEvent; -- (void) otherMouseDown: (NSEvent*) theEvent; -- (void) otherMouseUp: (NSEvent*) theEvent; + - (void) windowDidResize: (NSNotification*) notification; - (void) windowDidMove: (NSNotification*) notification; - (BOOL) windowClosingImpl: (BOOL) force; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 96965b67a..5ccd9c658 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -86,6 +86,88 @@ static jfloat GetDelta(NSEvent *event, jint javaMods[]) { return (jfloat) delta; } +#define kVK_Shift 0x38 +#define kVK_Option 0x3A +#define kVK_Control 0x3B +#define kVK_Command 0x37 + +static jint mods2JavaMods(NSUInteger mods) +{ + int javaMods = 0; + if (mods & NSShiftKeyMask) { + javaMods |= EVENT_SHIFT_MASK; + } + if (mods & NSControlKeyMask) { + javaMods |= EVENT_CTRL_MASK; + } + if (mods & NSCommandKeyMask) { + javaMods |= EVENT_META_MASK; + } + if (mods & NSAlternateKeyMask) { + javaMods |= EVENT_ALT_MASK; + } + return javaMods; +} + +static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) { + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + UCKeyTranslate(keyboardLayout, keyCode, + kUCKeyActionDisplay, 0, + LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, + &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars); + + return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); +} + +static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) { + CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL); + if ( NULL != codeToCharDict ) { + intptr_t i; + for (i = 0; i < 128; ++i) { + CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout); + if( NULL != string ) { + CFIndex stringLen = CFStringGetLength (string); + if ( 0 < stringLen ) { + UniChar character = CFStringGetCharacterAtIndex(string, 0); + DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character); + CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character); + } + CFRelease(string); + } + } + } + return codeToCharDict; +} + +static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL; + +static void CKCH_CreateDictionaries() { + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard); + CFRelease(currentKeyboard); +} + +static UniChar CKCH_CharForKeyCode(jshort keyCode) { + UniChar rChar = 0; + + if ( NULL != CKCH_USCodeToNNChar ) { + intptr_t code = (intptr_t) keyCode; + intptr_t character = 0; + + if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) { + rChar = (UniChar) character; + DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar); + } + } + return rChar; +} + static jmethodID enqueueMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; static jmethodID requestFocusID = NULL; @@ -122,6 +204,16 @@ static jmethodID windowRepaintID = NULL; pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive ptrTrackingTag = 0; + myCursor = NULL; + + modsDown[0] = NO; // shift + modsDown[1] = NO; // ctrl + modsDown[2] = NO; // alt + modsDown[3] = NO; // win + mouseConfined = NO; + mouseVisible = YES; + mouseInside = NO; + cursorIsHidden = NO; DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]); return res; @@ -144,10 +236,9 @@ static jmethodID windowRepaintID = NULL; if( 0 < softLockCount ) { NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n"); } - if(0 != ptrTrackingTag) { - [self removeTrackingRect: ptrTrackingTag]; - ptrTrackingTag = 0; - } + [self removeCursorRects]; + [self removeMyCursor]; + pthread_mutex_destroy(&softLockSync); DBG_PRINT("NewtView::dealloc.X: %p\n", self); [super dealloc]; @@ -182,26 +273,6 @@ static jmethodID windowRepaintID = NULL; return javaWindowObject; } -- (void) rightMouseDown: (NSEvent*) theEvent -{ - NSResponder* next = [self nextResponder]; - if (next != nil) { - [next rightMouseDown: theEvent]; - } -} - -- (void) resetCursorRects -{ - [super resetCursorRects]; - - if(0 != ptrTrackingTag) { - [self removeTrackingRect: ptrTrackingTag]; - ptrTrackingTag = 0; - } - ptrRect = [self bounds]; - ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO]; -} - - (void) setDestroyNotifySent: (BOOL) v { destroyNotifySent = v; @@ -337,141 +408,462 @@ static jmethodID windowRepaintID = NULL; return YES; } -@end - -static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) { - UInt32 keysDown = 0; - UniChar chars[4]; - UniCharCount realLength; - - UCKeyTranslate(keyboardLayout, keyCode, - kUCKeyActionDisplay, 0, - LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, - &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars); - - return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); +- (BOOL) becomeFirstResponder +{ + DBG_PRINT( "*************** View.becomeFirstResponder\n"); + return [super becomeFirstResponder]; } -static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) { - CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); - const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); +- (BOOL) resignFirstResponder +{ + DBG_PRINT( "*************** View.resignFirstResponder\n"); + return [super resignFirstResponder]; +} - CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL); - if ( NULL != codeToCharDict ) { - intptr_t i; - for (i = 0; i < 128; ++i) { - CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout); - if( NULL != string ) { - CFIndex stringLen = CFStringGetLength (string); - if ( 0 < stringLen ) { - UniChar character = CFStringGetCharacterAtIndex(string, 0); - DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character); - CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character); - } - CFRelease(string); - } +- (void) removeCursorRects +{ + if(0 != ptrTrackingTag) { + if(NULL != myCursor) { + [self removeCursorRect: ptrRect cursor: myCursor]; } + [self removeTrackingRect: ptrTrackingTag]; + ptrTrackingTag = 0; } - return codeToCharDict; } -static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL; +- (void) addCursorRects +{ + ptrRect = [self bounds]; + if(NULL != myCursor) { + [self addCursorRect: ptrRect cursor: myCursor]; + } + ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO]; +} -static void CKCH_CreateDictionaries() { - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); - CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard); - CFRelease(currentKeyboard); +- (void) removeMyCursor +{ + if(NULL != myCursor) { + [myCursor release]; + myCursor = NULL; + } } -static UniChar CKCH_CharForKeyCode(jshort keyCode) { - UniChar rChar = 0; +- (void) resetCursorRects +{ + [super resetCursorRects]; - if ( NULL != CKCH_USCodeToNNChar ) { - intptr_t code = (intptr_t) keyCode; - intptr_t character = 0; + [self removeCursorRects]; + [self addCursorRects]; +} - if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) { - rChar = (UniChar) character; - DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar); +- (void) setPointerIcon: (NSCursor*)c +{ + DBG_PRINT( "setPointerIcon: %p -> %p, top %p, mouseInside %d\n", myCursor, c, [NSCursor currentCursor], (int)mouseInside); + if( c != myCursor ) { + [self removeCursorRects]; + [self removeMyCursor]; + myCursor = c; + if( NULL != myCursor ) { + [myCursor retain]; } } - return rChar; + NSWindow* nsWin = [self window]; + if( NULL != nsWin ) { + [nsWin invalidateCursorRectsForView: self]; + } } -@implementation NewtMacWindow - -+ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz +- (void) mouseEntered: (NSEvent*) theEvent { - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); - if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && - positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) - { - CKCH_CreateDictionaries(); - return YES; + DBG_PRINT( "mouseEntered: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]); + mouseInside = YES; + [self cursorHide: !mouseVisible enter: 1]; + if(NO == mouseConfined) { + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; + } + NSWindow* nsWin = [self window]; + if( NULL != nsWin ) { + [nsWin makeFirstResponder: self]; } - return NO; } -- (id) initWithContentRect: (NSRect) contentRect - styleMask: (NSUInteger) windowStyle - backing: (NSBackingStoreType) bufferingType - defer: (BOOL) deferCreation - isFullscreenWindow:(BOOL)isfs +- (void) mouseExited: (NSEvent*) theEvent { - id res = [super initWithContentRect: contentRect - styleMask: windowStyle - backing: bufferingType - defer: deferCreation]; - // OSX 10.6 - if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && - [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { - hasPresentationSwitch = YES; - defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; - fullscreenPresentationOptions = - // NSApplicationPresentationDefault| - // NSApplicationPresentationAutoHideDock| - NSApplicationPresentationHideDock| - // NSApplicationPresentationAutoHideMenuBar| - NSApplicationPresentationHideMenuBar| - NSApplicationPresentationDisableAppleMenu| - // NSApplicationPresentationDisableProcessSwitching| - // NSApplicationPresentationDisableSessionTermination| - NSApplicationPresentationDisableHideApplication| - // NSApplicationPresentationDisableMenuBarTransparency| - // NSApplicationPresentationFullScreen| // OSX 10.7 - 0 ; + DBG_PRINT( "mouseExited: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]); + if(NO == mouseConfined) { + mouseInside = NO; + [self cursorHide: NO enter: -1]; + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; + [self resignFirstResponder]; } else { - hasPresentationSwitch = NO; - defaultPresentationOptions = 0; - fullscreenPresentationOptions = 0; + [self setMousePosition: lastInsideMousePosition]; } +} - isFullscreenWindow = isfs; - // Why is this necessary? Without it we don't get any of the - // delegate methods like resizing and window movement. - [self setDelegate: self]; - cachedInsets[0] = 0; // l - cachedInsets[1] = 0; // r - cachedInsets[2] = 0; // t - cachedInsets[3] = 0; // b - modsDown[0] = NO; // shift - modsDown[1] = NO; // ctrl - modsDown[2] = NO; // alt - modsDown[3] = NO; // win - mouseConfined = NO; - mouseVisible = YES; - mouseInside = NO; - cursorIsHidden = NO; - customCursor = NULL; +- (void) setMousePosition:(NSPoint)p +{ + NSWindow* nsWin = [self window]; + if( NULL != nsWin ) { + NSScreen* screen = [nsWin screen]; + NSRect screenRect = [screen frame]; + + CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) + CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); + CGEventPost (kCGHIDEventTap, ev); + } +} + +- (BOOL) updateMouseInside +{ + NSRect viewFrame = [self frame]; + NSPoint l1 = [NSEvent mouseLocation]; + NSPoint l0 = [self screenPos2NewtClientWinPos: l1]; + mouseInside = viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) && + viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ; + return mouseInside; +} + +- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus +{ + mouseVisible = v; + [self updateMouseInside]; + DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n", + mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus); + if(YES == focus && YES == mouseInside) { + [self cursorHide: !mouseVisible enter: 0]; + } +} +- (BOOL) isMouseVisible +{ + return mouseVisible; +} + +- (void) cursorHide:(BOOL)v enter:(int)enterState +{ + DBG_PRINT( "cursorHide: %d -> %d, enter %d; PointerIcon: %p, top %p\n", + cursorIsHidden, v, enterState, myCursor, [NSCursor currentCursor]); + if(v) { + if(!cursorIsHidden) { + [NSCursor hide]; + cursorIsHidden = YES; + } + } else { + if(cursorIsHidden) { + [NSCursor unhide]; + cursorIsHidden = NO; + } + } +} + +- (void) setMouseConfined:(BOOL)v +{ + mouseConfined = v; + DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible); +} + +- (void) mouseMoved: (NSEvent*) theEvent +{ + if( mouseInside ) { + NSCursor * currentCursor = [NSCursor currentCursor]; + BOOL setCursor = NULL != myCursor && NO == cursorIsHidden && currentCursor != myCursor; + DBG_PRINT( "mouseMoved.set: %d; mouseInside %d, CursorHidden %d, PointerIcon: %p, top %p\n", + setCursor, mouseInside, cursorIsHidden, myCursor, currentCursor); + if( setCursor ) { + // FIXME: Workaround missing NSCursor update for 'fast moving' pointer + [myCursor set]; + } + lastInsideMousePosition = [NSEvent mouseLocation]; + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; + } +} + +- (void) scrollWheel: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED]; +} + +- (void) mouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) mouseDragged: (NSEvent*) theEvent +{ + lastInsideMousePosition = [NSEvent mouseLocation]; + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) mouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) rightMouseDown: (NSEvent*) theEvent +{ + NSResponder* next = [self nextResponder]; + if (next != nil) { + [next rightMouseDown: theEvent]; + } + // FIXME: ^^ OR [super rightMouseDown: theEvent] ? + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) rightMouseDragged: (NSEvent*) theEvent +{ + lastInsideMousePosition = [NSEvent mouseLocation]; + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) rightMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) otherMouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) otherMouseDragged: (NSEvent*) theEvent +{ + lastInsideMousePosition = [NSEvent mouseLocation]; + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) otherMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType +{ + if (javaWindowObject == NULL) { + DBG_PRINT("sendMouseEvent: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JNIEnv* env; + if( NULL != jvmHandle ) { + env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + } else { + env = NULL; + } + if(NULL==env) { + DBG_PRINT("sendMouseEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + return; + } + jint javaMods[] = { 0 } ; + javaMods[0] = mods2JavaMods([event modifierFlags]); + + // convert to 1-based button number (or use zero if no button is involved) + // TODO: detect mouse button when mouse wheel scrolled + jshort javaButtonNum = 0; + jfloat scrollDeltaY = 0.0f; + switch ([event type]) { + case NSScrollWheel: { + scrollDeltaY = GetDelta(event, javaMods); + javaButtonNum = 1; + break; + } + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSLeftMouseDragged: + javaButtonNum = 1; + break; + case NSRightMouseDown: + case NSRightMouseUp: + case NSRightMouseDragged: + javaButtonNum = 3; + break; + case NSOtherMouseDown: + case NSOtherMouseUp: + case NSOtherMouseDragged: + javaButtonNum = 2; + break; + } + + if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) { + // ignore 0 increment wheel scroll events + return; + } + if (evType == EVENT_MOUSE_PRESSED) { + (*env)->CallVoidMethod(env, javaWindowObject, requestFocusID, JNI_FALSE); + } + + NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; + + (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, + evType, javaMods[0], + (jint) location.x, (jint) location.y, + javaButtonNum, scrollDeltaY); + + /* if (shallBeDetached) { + (*jvmHandle)->DetachCurrentThread(jvmHandle); + } */ +} + +- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p +{ + NSRect viewFrame = [self frame]; + + NSRect r; + r.origin.x = p.x; + r.origin.y = p.y; + r.size.width = 0; + r.size.height = 0; + // NSRect rS = [[self window] convertRectFromScreen: r]; // 10.7 + NSPoint oS = [[self window] convertScreenToBase: r.origin]; + oS.y = viewFrame.size.height - oS.y; // y-flip + return oS; +} + +- (void) handleFlagsChanged:(NSUInteger) mods +{ + [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods]; + [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods]; + [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods]; + [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods]; +} + +- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods +{ + if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) { + modsDown[keyIdx] = YES; + [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED]; + } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) { + modsDown[keyIdx] = NO; + [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED]; + } +} + +- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType +{ + jshort keyCode = (jshort) [event keyCode]; + NSString* chars = [event charactersIgnoringModifiers]; + NSUInteger mods = [event modifierFlags]; + [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType]; +} + +- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType +{ + if (javaWindowObject == NULL) { + DBG_PRINT("sendKeyEvent: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JNIEnv* env; + if( NULL != jvmHandle ) { + env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + } else { + env = NULL; + } + if(NULL==env) { + DBG_PRINT("sendKeyEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + return; + } + + int i; + int len = NULL != chars ? [chars length] : 0; + jint javaMods = mods2JavaMods(mods); + + if(len > 0) { + // printable chars + for (i = 0; i < len; i++) { + // Note: the key code in the NSEvent does not map to anything we can use + UniChar keyChar = (UniChar) [chars characterAtIndex: i]; + UniChar keySymChar = CKCH_CharForKeyCode(keyCode); + + DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, + (int)mods, (int)javaMods, (int)keySymChar); + + (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); + } + } else { + // non-printable chars + jchar keyChar = (jchar) 0; + + DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); + + (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, keyChar, keyChar); + } + + /* if (shallBeDetached) { + (*jvmHandle)->DetachCurrentThread(jvmHandle); + } */ +} + +@end + +@implementation NewtMacWindow + ++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz +{ + enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); + enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); + requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); + if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && + positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) + { + CKCH_CreateDictionaries(); + return YES; + } + return NO; +} + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (NSUInteger) windowStyle + backing: (NSBackingStoreType) bufferingType + defer: (BOOL) deferCreation + isFullscreenWindow:(BOOL)isfs +{ + id res = [super initWithContentRect: contentRect + styleMask: windowStyle + backing: bufferingType + defer: deferCreation]; + // OSX 10.6 + if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && + [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { + hasPresentationSwitch = YES; + defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; + fullscreenPresentationOptions = + // NSApplicationPresentationDefault| + // NSApplicationPresentationAutoHideDock| + NSApplicationPresentationHideDock| + // NSApplicationPresentationAutoHideMenuBar| + NSApplicationPresentationHideMenuBar| + NSApplicationPresentationDisableAppleMenu| + // NSApplicationPresentationDisableProcessSwitching| + // NSApplicationPresentationDisableSessionTermination| + NSApplicationPresentationDisableHideApplication| + // NSApplicationPresentationDisableMenuBarTransparency| + // NSApplicationPresentationFullScreen| // OSX 10.7 + 0 ; + } else { + hasPresentationSwitch = NO; + defaultPresentationOptions = 0; + fullscreenPresentationOptions = 0; + } + + isFullscreenWindow = isfs; + // Why is this necessary? Without it we don't get any of the + // delegate methods like resizing and window movement. + [self setDelegate: self]; + cachedInsets[0] = 0; // l + cachedInsets[1] = 0; // r + cachedInsets[2] = 0; // t + cachedInsets[3] = 0; // b realized = YES; DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n", res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]); @@ -577,343 +969,79 @@ static UniChar CKCH_CharForKeyCode(jshort keyCode) { NSScreen* screen = [self screen]; NSRect screenFrame = [screen frame]; - DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n", - (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height); - - NSPoint r = NSMakePoint(screenFrame.origin.x + p.x, - screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); - - DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y); - - return r; -} - -/** - * p rel client window position w/ top-left origin - * returns: abs screen position w/ bottom-left origin - */ -- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p -{ - NSRect winFrame = [self frame]; - - NSView* mView = [self contentView]; - NSRect mViewFrame = [mView frame]; - - return NSMakePoint(winFrame.origin.x + p.x, - winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view -} - -- (NSSize) newtClientSize2TLSize: (NSSize) nsz -{ - NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom - return topSZ; -} - -/** - * y-flips input / output - * p rel client window position w/ top-left origin - * returns: location in 0/0 top-left space. - */ -- (NSPoint) getLocationOnScreen: (NSPoint) p -{ - NSScreen* screen = [self screen]; - NSRect screenRect = [screen frame]; - - NSView* view = [self contentView]; - NSRect viewFrame = [view frame]; - - NSRect r; - r.origin.x = p.x; - r.origin.y = viewFrame.size.height - p.y; // y-flip - r.size.width = 0; - r.size.height = 0; - // NSRect rS = [win convertRectToScreen: r]; // 10.7 - NSPoint oS = [self convertBaseToScreen: r.origin]; - oS.y = screenRect.origin.y + screenRect.size.height - oS.y; - return oS; -} - -- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p -{ - NSView* view = [self contentView]; - NSRect viewFrame = [view frame]; - - NSRect r; - r.origin.x = p.x; - r.origin.y = p.y; - r.size.width = 0; - r.size.height = 0; - // NSRect rS = [win convertRectFromScreen: r]; // 10.7 - NSPoint oS = [self convertScreenToBase: r.origin]; - oS.y = viewFrame.size.height - oS.y; // y-flip - return oS; -} - -- (BOOL) isMouseInside -{ - NSView* view = [self contentView]; - NSRect viewFrame = [view frame]; - NSPoint l1 = [NSEvent mouseLocation]; - NSPoint l0 = [self screenPos2NewtClientWinPos: l1]; - return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) && - viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ; -} - -- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus -{ - mouseVisible = v; - mouseInside = [self isMouseInside]; - DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n", - mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus); - if(YES == focus && YES == mouseInside) { - [self cursorHide: !mouseVisible enter: 0]; - } -} - -- (void) setPointerIcon:(NSCursor*)c -{ - DBG_PRINT( "setPointerIcon: mouseInside cursor: %p -> %p (glob %p), mouseInside %d\n", customCursor, c, [NSCursor currentCursor], (int)mouseInside); - if(YES == mouseInside) { - if( NULL != c ) { - DBG_PRINT( "setPointerIcon push: %p\n", c); - [c push]; - } else if( NULL != customCursor ) { - if ( NO == [customCursor isKindOfClass:[NSCursor class]] ) { - DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (2)\n", customCursor); - if( [NSCursor currentCursor] == customCursor ) { - [NSCursor pop]; - } - } else if( [NSCursor currentCursor] == customCursor ) { - DBG_PRINT( "setPointerIcon pop: %p\n", customCursor); - [customCursor pop]; - } - } - } - customCursor = c; -} - -- (void) cursorHide:(BOOL)v enter:(int)enterState -{ - DBG_PRINT( "cursorHide: %d -> %d, enter %d\n", cursorIsHidden, v, enterState); - if( NULL != customCursor ) { - if ( NO == [customCursor isKindOfClass:[NSCursor class]] ) { - DBG_PRINT( "setPointerIcon0 NSCursor %p - is of invalid type (3)\n", customCursor); - if( [NSCursor currentCursor] == customCursor ) { - [NSCursor pop]; - } - } else { - if( 1 == enterState && [NSCursor currentCursor] != customCursor ) { - DBG_PRINT( "cursorHide.PointerIcon push: %p\n", customCursor); - [customCursor push]; - } else if( -1 == enterState && [NSCursor currentCursor] == customCursor ) { - DBG_PRINT( "cursorHide.PointerIcon pop: %p\n", customCursor); - [customCursor pop]; - } - } - } - if(v) { - if(!cursorIsHidden) { - [NSCursor hide]; - cursorIsHidden = YES; - } - } else { - if(cursorIsHidden) { - [NSCursor unhide]; - cursorIsHidden = NO; - } - } -} - -- (void) setMouseConfined:(BOOL)v -{ - mouseConfined = v; - DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible); -} - -- (void) setMousePosition:(NSPoint)p -{ - NSScreen* screen = [self screen]; - NSRect screenRect = [screen frame]; - - CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) - CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); - CGEventPost (kCGHIDEventTap, ev); -} - -static jint mods2JavaMods(NSUInteger mods) -{ - int javaMods = 0; - if (mods & NSShiftKeyMask) { - javaMods |= EVENT_SHIFT_MASK; - } - if (mods & NSControlKeyMask) { - javaMods |= EVENT_CTRL_MASK; - } - if (mods & NSCommandKeyMask) { - javaMods |= EVENT_META_MASK; - } - if (mods & NSAlternateKeyMask) { - javaMods |= EVENT_ALT_MASK; - } - return javaMods; -} - -- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType -{ - jshort keyCode = (jshort) [event keyCode]; - NSString* chars = [event charactersIgnoringModifiers]; - NSUInteger mods = [event modifierFlags]; - [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType]; -} - -- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType -{ - NSView* nsview = [self contentView]; - if( ! [nsview isKindOfClass:[NewtView class]] ) { - return; - } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; - if (javaWindowObject == NULL) { - DBG_PRINT("sendKeyEvent: null javaWindowObject\n"); - return; - } - int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } - if(NULL==env) { - DBG_PRINT("sendKeyEvent: JVM %p JNIEnv %p\n", jvmHandle, env); - return; - } - - int i; - int len = NULL != chars ? [chars length] : 0; - jint javaMods = mods2JavaMods(mods); - - if(len > 0) { - // printable chars - for (i = 0; i < len; i++) { - // Note: the key code in the NSEvent does not map to anything we can use - UniChar keyChar = (UniChar) [chars characterAtIndex: i]; - UniChar keySymChar = CKCH_CharForKeyCode(keyCode); - - DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, (int)keySymChar); - - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); - } - } else { - // non-printable chars - jchar keyChar = (jchar) 0; + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n", + (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height); - DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); + NSPoint r = NSMakePoint(screenFrame.origin.x + p.x, + screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyChar, keyChar); - } + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + return r; } -- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType +/** + * p rel client window position w/ top-left origin + * returns: abs screen position w/ bottom-left origin + */ +- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p { - NSView* nsview = [self contentView]; - if( ! [nsview isKindOfClass:[NewtView class]] ) { - return; - } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; - if (javaWindowObject == NULL) { - DBG_PRINT("sendMouseEvent: null javaWindowObject\n"); - return; - } - int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } - if(NULL==env) { - DBG_PRINT("sendMouseEvent: JVM %p JNIEnv %p\n", jvmHandle, env); - return; - } - jint javaMods[] = { 0 } ; - javaMods[0] = mods2JavaMods([event modifierFlags]); + NSRect winFrame = [self frame]; - // convert to 1-based button number (or use zero if no button is involved) - // TODO: detect mouse button when mouse wheel scrolled - jshort javaButtonNum = 0; - jfloat scrollDeltaY = 0.0f; - switch ([event type]) { - case NSScrollWheel: { - scrollDeltaY = GetDelta(event, javaMods); - javaButtonNum = 1; - break; - } - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSLeftMouseDragged: - javaButtonNum = 1; - break; - case NSRightMouseDown: - case NSRightMouseUp: - case NSRightMouseDragged: - javaButtonNum = 3; - break; - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - javaButtonNum = 2; - break; - } + NSView* mView = [self contentView]; + NSRect mViewFrame = [mView frame]; - if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) { - // ignore 0 increment wheel scroll events - return; - } - if (evType == EVENT_MOUSE_PRESSED) { - (*env)->CallVoidMethod(env, javaWindowObject, requestFocusID, JNI_FALSE); - } + return NSMakePoint(winFrame.origin.x + p.x, + winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view +} - NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; +- (NSSize) newtClientSize2TLSize: (NSSize) nsz +{ + NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom + return topSZ; +} - (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, - evType, javaMods[0], - (jint) location.x, (jint) location.y, - javaButtonNum, scrollDeltaY); +/** + * y-flips input / output + * p rel client window position w/ top-left origin + * returns: location in 0/0 top-left space. + */ +- (NSPoint) getLocationOnScreen: (NSPoint) p +{ + NSScreen* screen = [self screen]; + NSRect screenRect = [screen frame]; - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + NSView* view = [self contentView]; + NSRect viewFrame = [view frame]; + + NSRect r; + r.origin.x = p.x; + r.origin.y = viewFrame.size.height - p.y; // y-flip + r.size.width = 0; + r.size.height = 0; + // NSRect rS = [win convertRectToScreen: r]; // 10.7 + NSPoint oS = [self convertBaseToScreen: r.origin]; + oS.y = screenRect.origin.y + screenRect.size.height - oS.y; + return oS; } - (void) focusChanged: (BOOL) gained { DBG_PRINT( "focusChanged: gained %d\n", gained); - NSView* nsview = [self contentView]; - if( ! [nsview isKindOfClass:[NewtView class]] ) { + NewtView* newtView = (NewtView *) [self contentView]; + if( ! [newtView isKindOfClass:[NewtView class]] ) { return; } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; + jobject javaWindowObject = [newtView getJavaWindowObject]; if (javaWindowObject == NULL) { DBG_PRINT("focusChanged: null javaWindowObject\n"); return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; + JavaVM *jvmHandle = [newtView getJVMHandle]; JNIEnv* env; if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); } else { env = NULL; } @@ -929,15 +1057,50 @@ static jint mods2JavaMods(NSUInteger mods) } */ } +- (void) keyDown: (NSEvent*) theEvent +{ + NewtView* newtView = (NewtView *) [self contentView]; + if( [newtView isKindOfClass:[NewtView class]] ) { + [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED]; + } +} + +- (void) keyUp: (NSEvent*) theEvent +{ + NewtView* newtView = (NewtView *) [self contentView]; + if( [newtView isKindOfClass:[NewtView class]] ) { + [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED]; + } +} + +- (void) flagsChanged:(NSEvent *) theEvent +{ + NSUInteger mods = [theEvent modifierFlags]; + NewtView* newtView = (NewtView *) [self contentView]; + if( [newtView isKindOfClass:[NewtView class]] ) { + [newtView handleFlagsChanged: mods]; + } +} + +- (BOOL) acceptsMouseMovedEvents +{ + return YES; +} + +- (BOOL) acceptsFirstResponder +{ + return YES; +} + - (BOOL) becomeFirstResponder { - DBG_PRINT( "*************** becomeFirstResponder\n"); + DBG_PRINT( "*************** Win.becomeFirstResponder\n"); return [super becomeFirstResponder]; } - (BOOL) resignFirstResponder { - DBG_PRINT( "*************** resignFirstResponder\n"); + DBG_PRINT( "*************** Win.resignFirstResponder\n"); return [super resignFirstResponder]; } @@ -965,9 +1128,12 @@ static jint mods2JavaMods(NSUInteger mods) - (void) windowDidBecomeKey: (NSNotification *) notification { DBG_PRINT( "*************** windowDidBecomeKey\n"); - mouseInside = [self isMouseInside]; - if(YES == mouseInside) { - [self cursorHide: !mouseVisible enter: 0]; + NewtView* newtView = (NewtView *) [self contentView]; + if( [newtView isKindOfClass:[NewtView class]] ) { + BOOL mouseInside = [newtView updateMouseInside]; + if(YES == mouseInside) { + [newtView cursorHide: ![newtView isMouseVisible] enter: 1]; + } } [self focusChanged: YES]; } @@ -979,128 +1145,6 @@ static jint mods2JavaMods(NSUInteger mods) [self focusChanged: NO]; } -- (void) keyDown: (NSEvent*) theEvent -{ - [self sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED]; -} - -- (void) keyUp: (NSEvent*) theEvent -{ - [self sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED]; -} - -#define kVK_Shift 0x38 -#define kVK_Option 0x3A -#define kVK_Control 0x3B -#define kVK_Command 0x37 - -- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods -{ - if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) { - modsDown[keyIdx] = YES; - [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED]; - } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) { - modsDown[keyIdx] = NO; - [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED]; - } -} - -- (void) flagsChanged:(NSEvent *) theEvent -{ - NSUInteger mods = [theEvent modifierFlags]; - - // BOOL modsDown[4]; // shift, ctrl, alt/option, win/command - - [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods]; - [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods]; - [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods]; - [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods]; -} - -- (void) mouseEntered: (NSEvent*) theEvent -{ - DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible); - mouseInside = YES; - [self cursorHide: !mouseVisible enter: 1]; - if(NO == mouseConfined) { - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; - } -} - -- (void) mouseExited: (NSEvent*) theEvent -{ - DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible); - if(NO == mouseConfined) { - mouseInside = NO; - [self cursorHide: NO enter: -1]; - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; - } else { - [self setMousePosition: lastInsideMousePosition]; - } -} - -- (void) mouseMoved: (NSEvent*) theEvent -{ - lastInsideMousePosition = [NSEvent mouseLocation]; - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; -} - -- (void) scrollWheel: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED]; -} - -- (void) mouseDown: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; -} - -- (void) mouseDragged: (NSEvent*) theEvent -{ - lastInsideMousePosition = [NSEvent mouseLocation]; - // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; -} - -- (void) mouseUp: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; -} - -- (void) rightMouseDown: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; -} - -- (void) rightMouseDragged: (NSEvent*) theEvent -{ - lastInsideMousePosition = [NSEvent mouseLocation]; - // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; -} - -- (void) rightMouseUp: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; -} - -- (void) otherMouseDown: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; -} - -- (void) otherMouseDragged: (NSEvent*) theEvent -{ - lastInsideMousePosition = [NSEvent mouseLocation]; - // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; -} - -- (void) otherMouseUp: (NSEvent*) theEvent -{ - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; -} - - (void)windowDidResize: (NSNotification*) notification { JNIEnv* env = NULL; @@ -1108,14 +1152,13 @@ static jint mods2JavaMods(NSUInteger mods) int shallBeDetached = 0; JavaVM *jvmHandle = NULL; - NSView* nsview = [self contentView]; - if( [nsview isKindOfClass:[NewtView class]] ) { - NewtView* view = (NewtView *) nsview; - javaWindowObject = [view getJavaWindowObject]; + NewtView* newtView = (NewtView *) [self contentView]; + if( [newtView isKindOfClass:[NewtView class]] ) { + javaWindowObject = [newtView getJavaWindowObject]; if (javaWindowObject != NULL) { - jvmHandle = [view getJVMHandle]; + jvmHandle = [newtView getJVMHandle]; if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); } } } @@ -1139,21 +1182,20 @@ static jint mods2JavaMods(NSUInteger mods) - (void)windowDidMove: (NSNotification*) notification { - NSView* nsview = [self contentView]; - if( ! [nsview isKindOfClass:[NewtView class]] ) { + NewtView* newtView = (NewtView *) [self contentView]; + if( ! [newtView isKindOfClass:[NewtView class]] ) { return; } - NewtView* view = (NewtView *) nsview; - jobject javaWindowObject = [view getJavaWindowObject]; + jobject javaWindowObject = [newtView getJavaWindowObject]; if (javaWindowObject == NULL) { DBG_PRINT("windowDidMove: null javaWindowObject\n"); return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; + JavaVM *jvmHandle = [newtView getJVMHandle]; JNIEnv* env; if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); } else { env = NULL; } @@ -1186,32 +1228,31 @@ static jint mods2JavaMods(NSUInteger mods) jboolean closed = JNI_FALSE; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [self cursorHide: NO enter: -1]; - - NSView* nsview = [self contentView]; - if( ! [nsview isKindOfClass:[NewtView class]] ) { + NewtView* newtView = (NewtView *) [self contentView]; + if( ! [newtView isKindOfClass:[NewtView class]] ) { return NO; } - NewtView* view = (NewtView *) nsview; - if( false == [view getDestroyNotifySent] ) { - jobject javaWindowObject = [view getJavaWindowObject]; + [newtView cursorHide: NO enter: -1]; + + if( false == [newtView getDestroyNotifySent] ) { + jobject javaWindowObject = [newtView getJavaWindowObject]; DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); return NO; } int shallBeDetached = 0; - JavaVM *jvmHandle = [view getJVMHandle]; + JavaVM *jvmHandle = [newtView getJVMHandle]; JNIEnv* env = NULL; NS_DURING if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); + env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); } NS_HANDLER jvmHandle = NULL; env = NULL; - [view setJVMHandle: NULL]; + [newtView setJVMHandle: NULL]; DBG_PRINT("windowWillClose: JVMHandler Exception\n"); NS_ENDHANDLER DBG_PRINT("windowWillClose: JVM %p JNIEnv %p\n", jvmHandle, env); @@ -1219,11 +1260,11 @@ NS_ENDHANDLER return NO; } - [view setDestroyNotifySent: true]; // earmark assumption of being closed + [newtView setDestroyNotifySent: true]; // earmark assumption of being closed closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE); if(!force && !closed) { // not closed on java side, not force -> clear flag - [view setDestroyNotifySent: false]; + [newtView setDestroyNotifySent: false]; } /* if (shallBeDetached) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index efec961de..8cc676291 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -85,6 +85,7 @@ public class TestGearsES2NEWT extends UITestCase { static boolean waitForKey = false; static boolean mouseVisible = true; static boolean mouseConfined = false; + static boolean setPointerIcon = false; static boolean showFPS = false; static int loops = 1; static boolean loop_shutdown = false; @@ -183,6 +184,10 @@ public class TestGearsES2NEWT extends UITestCase { } pointerIconOne = _pointerIconOne; } + if( setPointerIcon ) { + glWindow.setPointerIcon(pointerIconOne); + System.err.println("Set PointerIcon: "+glWindow.getPointerIcon()); + } glWindow.addKeyListener(new KeyAdapter() { @Override @@ -216,16 +221,6 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); } }.start(); - } else if(e.getKeyChar()=='c') { - new Thread() { - public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); - System.err.println("[set pointer-icon pre]"); - final PointerIcon currentPI = glWindow.getPointerIcon(); - glWindow.setPointerIcon( currentPI == pointerIconOne ? null : pointerIconOne); - System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); - glWindow.setExclusiveContextThread(t); - } }.start(); } else if(e.getKeyChar()=='d') { new Thread() { public void run() { @@ -245,6 +240,16 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); } }.start(); + } else if(e.getKeyChar()=='c') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + glWindow.setPointerIcon( currentPI == pointerIconOne ? null : pointerIconOne); + System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); + glWindow.setExclusiveContextThread(t); + } }.start(); } else if(e.getKeyChar()=='i') { new Thread() { public void run() { @@ -482,6 +487,8 @@ public class TestGearsES2NEWT extends UITestCase { mouseVisible = false; } else if(args[i].equals("-mouseConfine")) { mouseConfined = true; + } else if(args[i].equals("-pointerIcon")) { + setPointerIcon = true; } else if(args[i].equals("-showFPS")) { showFPS = true; } else if(args[i].equals("-width")) { @@ -537,6 +544,7 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("pmvDirect "+(!pmvUseBackingArray)); System.err.println("mouseVisible "+mouseVisible); System.err.println("mouseConfined "+mouseConfined); + System.err.println("pointerIcon "+setPointerIcon); System.err.println("loops "+loops); System.err.println("loop shutdown "+loop_shutdown); System.err.println("forceES2 "+forceES2); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index 189645d3d..69874df6b 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -31,6 +31,10 @@ import java.awt.Frame; import javax.media.nativewindow.util.InsetsImmutable; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.Display; +import com.jogamp.newt.Window; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -42,6 +46,7 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter { final NewtCanvasAWT newtCanvasAWT; final GLWindow glWindow; final QuitAdapter quitAdapter; + PointerIcon pointerIconTest = null; public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow, QuitAdapter quitAdapter) { this.frame = frame; @@ -54,9 +59,7 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter { if( !e.isPrintableKey() || e.isAutoRepeat() ) { return; } - if( e.getKeySymbol() == KeyEvent.VK_I ) { - System.err.println(glWindow); - } else if( e.getKeySymbol() == KeyEvent.VK_L ) { + if( e.getKeySymbol() == KeyEvent.VK_L ) { javax.media.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null); javax.media.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); System.err.println("NewtCanvasAWT position: "+p0+", "+p1); @@ -140,6 +143,50 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter { quitAdapter.enable(true); } } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_C ) { + if( null == pointerIconTest ) { + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } ); + final Display disp = glWindow.getScreen().getDisplay(); + try { + pointerIconTest = disp.createPointerIcon(res, 16, 0); + } catch (Exception err) { + err.printStackTrace(); + } + } + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest); + System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if( e.getKeySymbol() == KeyEvent.VK_I ) { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible()); + glWindow.setPointerVisible(!glWindow.isPointerVisible()); + System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_J ) { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); + glWindow.confinePointer(!glWindow.isPointerConfined()); + System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_W ) { + new Thread() { + public void run() { + System.err.println("[set mouse pos pre]"); + glWindow.warpPointer(glWindow.getWidth()/2, glWindow.getHeight()/2); + System.err.println("[set mouse pos post]"); + } }.start(); } } } \ No newline at end of file -- cgit v1.2.3 From 69b5adb37a191e746fa55e495c2d02a942833899 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 5 Jan 2014 18:12:43 +0100 Subject: NEWT OSX: Add missing NewtCommon_init(env) (duh!) - Issuing NewtCommon_throwNewRuntimeException(..) if given references are of invalid type Missing NewtCommon_init(env) always lead to a crash when calling NewtCommon_throwNewRuntimeException(..) due to uninitialized clazz instances! --- .../jogamp/newt/driver/macosx/WindowDriver.java | 23 ++++----- src/newt/native/MacWindow.m | 59 ++++++++++------------ 2 files changed, 37 insertions(+), 45 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 748604994..edeb69f84 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -401,9 +401,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl OSXUtil.RunOnMainThread(true, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle ! @Override public void run() { - if( !setPointerIcon0(getWindowHandle(), piHandle) ) { - throw new RuntimeException("Failed: "+pi+", "+WindowDriver.this); - } + setPointerIcon0(getWindowHandle(), piHandle); } } ); } else { final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(this, true); @@ -430,9 +428,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl OSXUtil.RunOnMainThread(false, new Runnable() { @Override public void run() { - if( !setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible) ) { - throw new RuntimeException("Failed"); - } + setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible); } } ); return true; // setPointerVisible0 always returns true .. } else { @@ -456,7 +452,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected boolean confinePointerImpl(final boolean confine) { if( !isOffscreenInstance ) { - return confinePointer0(getWindowHandle(), confine); + confinePointer0(getWindowHandle(), confine); + return true; } // else may need offscreen solution ? FIXME return false; } @@ -464,9 +461,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected void warpPointerImpl(final int x, final int y) { if( !isOffscreenInstance ) { - if( !warpPointer0(getWindowHandle(), x, y) ) { - throw new RuntimeException("Failed"); - } + warpPointer0(getWindowHandle(), x, y); } // else may need offscreen solution ? FIXME } @@ -621,10 +616,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Must be called on Main-Thread */ private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); - private static native boolean setPointerIcon0(long windowHandle, long handle); - private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); - private static native boolean confinePointer0(long windowHandle, boolean confine); - private static native boolean warpPointer0(long windowHandle, int x, int y); + private static native void setPointerIcon0(long windowHandle, long handle); + private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); + private static native void confinePointer0(long windowHandle, boolean confine); + private static native void warpPointer0(long windowHandle, int x, int y); // Window styles private static final int NSBorderlessWindowMask = 0; diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index eb5913706..359b67b39 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -210,6 +210,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSAp if(initialized) return JNI_TRUE; initialized = 1; + NewtCommon_init(env); + // This little bit of magic is needed in order to receive mouse // motion events and allow key focus to be properly transferred. // FIXME: are these Carbon APIs? They come from the @@ -349,7 +351,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPoint { NSCursor * c = (NSCursor*) (intptr_t) handle ; if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { - DBG_PRINT( "Not a NSCursor %p\n", c); + NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c); return; } DBG_PRINT( "destroyPointerIcon0 %p\n", c); @@ -960,7 +962,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 NSWindow *pWin = [mWin parentWindow]; DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); if( !isNewtWin ) { - DBG_PRINT( "windowClose.0 - Not a NEWT win - abort\n"); + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -1316,38 +1318,36 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0 (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) { - NSObject *nsObj = (NSObject*) ((intptr_t) win); - NewtMacWindow * mWin = (NewtMacWindow*) nsObj; + NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win; if( ![mWin isKindOfClass:[NewtMacWindow class]] ) { - DBG_PRINT("Not a NewtMacWindow %p\n", nsObj); + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return NULL; } NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)]; return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y); } -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 (JNIEnv *env, jobject unused, jlong window, jlong handle) { NSCursor *c = (NSCursor*) (intptr_t) handle ; if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { - DBG_PRINT("Not a NSCursor %p\n", c); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c); + return; } NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { - DBG_PRINT("Not a NewtMacWindow %p\n", mWin); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); + return; } NewtView* nView = (NewtView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtView class]] ) { - DBG_PRINT("Not a NewtView %p\n", nView); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView); + return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setPointerIcon: c]; [pool release]; - return JNI_TRUE; } /* @@ -1355,24 +1355,23 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe * Method: setPointerVisible0 * Signature: (JZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { - DBG_PRINT("Not a NewtMacWindow %p\n", mWin); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); + return; } NewtView* nView = (NewtView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtView class]] ) { - DBG_PRINT("Not a NewtView %p\n", nView); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView); + return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; [pool release]; - return JNI_TRUE; } /* @@ -1380,23 +1379,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe * Method: confinePointer0 * Signature: (JZ)Z */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { - DBG_PRINT("Not a NewtMacWindow %p\n", mWin); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); + return; } NewtView* nView = (NewtView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtView class]] ) { - DBG_PRINT("Not a NewtView %p\n", nView); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView); + return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; [pool release]; - return JNI_TRUE; } /* @@ -1404,22 +1402,21 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePo * Method: warpPointer0 * Signature: (JJII)V */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { - DBG_PRINT("Not a NewtMacWindow %p\n", mWin); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); + return; } NewtView* nView = (NewtView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtView class]] ) { - DBG_PRINT("Not a NewtView %p\n", nView); - return JNI_FALSE; + NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView); + return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; [pool release]; - return JNI_TRUE; } -- cgit v1.2.3 From bd98b927b910d9421e63cf0dbc2b746eec019f80 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 8 Jan 2014 21:56:26 +0100 Subject: Bug 935: NEWT PointerIcon: Utilize Toolkit Agnostic PixelFormat and Conversion Utilities (Allowing 'arbitrary' PointerIcon data input) Commit fe28bc125429b38cdcd016746081f4a6d521c6fd added the notion of toolkit agnostic PixelFormat and conversion utilities, utilized and further tested by this patch. +++ - PointerIcon is a PixelRectangle and hence holds the decoded data. This allows on-the-fly conversion if required as well as recreation w/o PNG re-decoding. - Using array-backed PointerIcon data where possible, allowing better performance when converting PixelFormat etc. - NEWT Display adds 'createPointerIcon(final IOUtil.ClassResources pngResource...' method to support agnostic PointerIcon creation. - NEWT Display adds methods to allow users to avoid PixelFormat and Buffer NIO type forced conversion: - PixelFormat getNativePointerIconPixelFormat() - boolean getNativePointerIconForceDirectNIO() +++ PNGImage -> PNGPixelRect Deleted: com.jogamp.opengl.util.texture.spi.PNGImage Added: com.jogamp.opengl.util.PNGPixelRect (We hope nobody was using PNGImage directly since it was a service-plugin for TextureIO) PNGPixelRect is a PixelRectangle PNGPixelRect actually is implemented OpenGL agnostic, however - since our PNGJ support lives under package 'jogamp.opengl.util.pngj' it cannot be moved up (yet). PNGPixelRect now handles all PixelFormat for the target format and also added support for grayscale+alpha (2 channels). The latter is force-converted to RGB* - similar to paletted. Further more, PNGPixelRect allows simply passing an OutputStream to write the PNG data. Used by: TextureIO and NEWT +++ - OffscreenSurfaceLayer's setCursor(..) uses the agnostic PixelRectangle instead of a PNG resource. - AWTMisc uses the PixelRectangle to produce the AWT Cursor and converts it to the required format. Hence same pixels are used for NEWT and AWT pointer/cursor icon. - TestGearsES2Newt and NewtAWTReparentingKeyAdapter 'tests' iterate over 3 custom PointerIcon when pressed 'c'. - JOGLNewtAppletBase uses the new custom PointerIcon 'newt/data/crosshair-lumina-trans-32x32.png', which is included in NEWT (213 bytes only). - --- .../assets-test/crosshair-lumina-trans-64x64.png | Bin 0 -> 424 bytes .../newt/data/crosshair-lumina-trans-32x32.png | Bin 0 -> 213 bytes make/scripts/tests.sh | 9 +- .../com/jogamp/opengl/util/PNGPixelRect.java | 335 +++++++++++++++++++++ .../com/jogamp/opengl/util/texture/TextureIO.java | 63 ++-- .../jogamp/opengl/util/texture/spi/PNGImage.java | 319 -------------------- .../com/jogamp/nativewindow/awt/JAWTWindow.java | 17 +- .../media/nativewindow/OffscreenLayerSurface.java | 10 +- .../classes/jogamp/nativewindow/awt/AWTMisc.java | 48 ++- src/newt/classes/com/jogamp/newt/Display.java | 119 ++++++-- .../jogamp/newt/awt/applet/JOGLNewtAppletBase.java | 4 +- src/newt/classes/jogamp/newt/DisplayImpl.java | 156 +++++++++- src/newt/classes/jogamp/newt/PointerIconImpl.java | 63 +++- src/newt/classes/jogamp/newt/WindowImpl.java | 8 +- src/newt/classes/jogamp/newt/driver/PNGIcon.java | 35 +-- .../jogamp/newt/driver/macosx/DisplayDriver.java | 58 ++-- .../jogamp/newt/driver/opengl/JoglUtilPNGIcon.java | 92 ++---- .../jogamp/newt/driver/windows/DisplayDriver.java | 50 ++- .../jogamp/newt/driver/x11/DisplayDriver.java | 38 +-- .../jogamp/newt/driver/x11/WindowDriver.java | 20 +- src/newt/native/MacWindow.m | 32 +- src/newt/native/WindowsWindow.c | 16 +- src/newt/native/X11Display.c | 15 +- src/newt/native/X11Window.c | 20 +- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 59 +++- .../test/junit/jogl/util/texture/PNGTstFiles.java | 54 ++++ .../jogl/util/texture/TestPNGImage00NEWT.java | 92 ------ .../jogl/util/texture/TestPNGImage01NEWT.java | 182 ----------- .../jogl/util/texture/TestPNGPixelRect00NEWT.java | 224 ++++++++++++++ .../jogl/util/texture/TestPNGPixelRect01NEWT.java | 198 ++++++++++++ .../util/texture/TestPixelFormatUtil01NEWT.java | 105 +++++++ .../util/texture/crosshair-lumina-trans-32x32.png | Bin 0 -> 213 bytes .../util/texture/crosshair-lumina-trans-64x64.png | Bin 0 -> 424 bytes .../parenting/NewtAWTReparentingKeyAdapter.java | 62 +++- 34 files changed, 1573 insertions(+), 930 deletions(-) create mode 100644 make/resources/assets-test/crosshair-lumina-trans-64x64.png create mode 100644 make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png create mode 100644 src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png (limited to 'src/newt/native/MacWindow.m') diff --git a/make/resources/assets-test/crosshair-lumina-trans-64x64.png b/make/resources/assets-test/crosshair-lumina-trans-64x64.png new file mode 100644 index 000000000..9be285335 Binary files /dev/null and b/make/resources/assets-test/crosshair-lumina-trans-64x64.png differ diff --git a/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png b/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png new file mode 100644 index 000000000..92279640b Binary files /dev/null and b/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png differ diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index db852ce42..55973eb12 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -229,7 +229,7 @@ function jrun() { #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer" - #D_ARGS="-Djogl.debug.PNGImage" + #D_ARGS="-Djogl.debug.PNG -Dnewt.debug.Display.PointerIcon" #D_ARGS="-Djogl.debug.JPEGImage" #D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" #X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false" @@ -634,9 +634,10 @@ testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasA #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTBenchmarkNewtAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGTextureFromFileNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage00NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage01NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.ToolPNG2CSource $* +#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect00NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil00NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestGLReadBufferUtilTextureIOWrite01AWT $* diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java new file mode 100644 index 000000000..1bbc12f32 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java @@ -0,0 +1,335 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelRectangle; +import javax.media.nativewindow.util.PixelFormatUtil; + +import jogamp.opengl.Debug; +import jogamp.opengl.util.pngj.ImageInfo; +import jogamp.opengl.util.pngj.ImageLine; +import jogamp.opengl.util.pngj.ImageLineHelper; +import jogamp.opengl.util.pngj.PngReader; +import jogamp.opengl.util.pngj.PngWriter; +import jogamp.opengl.util.pngj.chunks.PngChunkPLTE; +import jogamp.opengl.util.pngj.chunks.PngChunkTRNS; +import jogamp.opengl.util.pngj.chunks.PngChunkTextVar; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.util.IOUtil; + +public class PNGPixelRect extends PixelRectangle.GenericPixelRect { + private static final boolean DEBUG = Debug.debug("PNG"); + + /** + * Reads a PNG image from the specified InputStream. + *

    + * Implicitly converts the image to match the desired: + *

      + *
    • {@link PixelFormat}, see {@link #getPixelformat()}
    • + *
    • destStrideInBytes, see {@link #getStride()}
    • + *
    • destIsGLOriented, see {@link #isGLOriented()}
    • + *
    + *

    + * + * @param in input stream + * @param destFmt desired destination {@link PixelFormat} incl. conversion, maybe null to use source {@link PixelFormat} + * @param destDirectBuffer if true, using a direct NIO buffer, otherwise an array backed buffer + * @param destMinStrideInBytes used if greater than PNG's stride, otherwise using PNG's stride. Stride is width * bytes-per-pixel. + * @param destIsGLOriented + * @return the newly created PNGPixelRect instance + * @throws IOException + */ + public static PNGPixelRect read(final InputStream in, + final PixelFormat ddestFmt, final boolean destDirectBuffer, final int destMinStrideInBytes, + final boolean destIsGLOriented) throws IOException { + final PngReader pngr = new PngReader(new BufferedInputStream(in), null); + final ImageInfo imgInfo = pngr.imgInfo; + final PngChunkPLTE plte = pngr.getMetadata().getPLTE(); + final PngChunkTRNS trns = pngr.getMetadata().getTRNS(); + final boolean indexed = imgInfo.indexed; + final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ; + + if(DEBUG) { + System.err.println("PNGPixelRect: "+imgInfo); + } + final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ; + final boolean isGrayAlpha = 2 == channels && imgInfo.greyscale && imgInfo.alpha; + if ( ! ( 1 == channels || 3 == channels || 4 == channels || isGrayAlpha ) ) { + throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 channels] or Lum+A (GA) images for now. Channels "+channels + " Paletted: " + indexed); + } + final int bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ; + if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel || isGrayAlpha ) ) { + throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel); + } + if( channels != bytesPerPixel ) { + throw new RuntimeException("PNGPixelRect currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel); + } + final int width = imgInfo.cols; + final int height = imgInfo.rows; + final double dpiX, dpiY; + { + final double[] dpi = pngr.getMetadata().getDpi(); + dpiX = dpi[0]; + dpiY = dpi[1]; + } + final PixelFormat srcFmt; + if ( indexed ) { + if ( hasAlpha ) { + srcFmt = PixelFormat.RGBA8888; + } else { + srcFmt = PixelFormat.RGB888; + } + } else { + switch( channels ) { + case 1: srcFmt = PixelFormat.LUMINANCE; break; + case 2: srcFmt = isGrayAlpha ? PixelFormat.LUMINANCE : null; break; + case 3: srcFmt = PixelFormat.RGB888; break; + case 4: srcFmt = PixelFormat.RGBA8888; break; + default: srcFmt = null; + } + if( null == srcFmt ) { + throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel); + } + } + final PixelFormat destFmt; + if( null == ddestFmt ) { + if( isGrayAlpha ) { + destFmt = PixelFormat.BGRA8888; // save alpha value on gray-alpha + } else { + destFmt = srcFmt; // 1:1 + } + } else { + destFmt = ddestFmt; // user choice + } + final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.bytesPerPixel() * width); + final ByteBuffer destPixels = destDirectBuffer ? Buffers.newDirectByteBuffer(destStrideInBytes * height) : + ByteBuffer.allocate(destStrideInBytes * height); + { + final int reqBytes = destStrideInBytes * height; + if( destPixels.limit() < reqBytes ) { + throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+destPixels); + } + } + final boolean vert_flip = destIsGLOriented; + + int[] rgbaScanline = indexed ? new int[width * channels] : null; + if(DEBUG) { + System.err.println("PNGPixelRect: indexed "+indexed+", alpha "+hasAlpha+", grayscale "+imgInfo.greyscale+", channels "+channels+"/"+imgInfo.channels+ + ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+ + ", grayAlpha "+isGrayAlpha+", pixels "+width+"x"+height+", dpi "+dpiX+"x"+dpiY+", format "+srcFmt); + System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", bytesPerPixel "+destFmt.bytesPerPixel()+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented); + System.err.println("PNGPixelRect: destStrideInBytes "+destStrideInBytes+" (destMinStrideInBytes "+destMinStrideInBytes+")"); + } + + for (int row = 0; row < height; row++) { + final ImageLine l1 = pngr.readRow(row); + int lineOff = 0; + int dataOff = vert_flip ? ( height - 1 - row ) * destStrideInBytes : row * destStrideInBytes; + if( indexed ) { + for (int j = width - 1; j >= 0; j--) { + rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized + dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, rgbaScanline, lineOff, hasAlpha); + lineOff += bytesPerPixel; + } + } else if( 1 == channels ) { + for (int j = width - 1; j >= 0; j--) { + dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)0xff); // Luminance, 1 bytesPerPixel + } + } else if( isGrayAlpha ) { + for (int j = width - 1; j >= 0; j--) { + dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)l1.scanline[lineOff++]); // Luminance+Alpha, 2 bytesPerPixel + } + } else if( srcFmt == destFmt ) { // fast-path + for (int j = width - 1; j >= 0; j--) { + dataOff = getPixelRGBSame(destPixels, dataOff, l1.scanline, lineOff, bytesPerPixel); + lineOff += bytesPerPixel; + } + } else { + for (int j = width - 1; j >= 0; j--) { + dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, l1.scanline, lineOff, hasAlpha); + lineOff += bytesPerPixel; + } + } + } + pngr.end(); + + return new PNGPixelRect(destFmt, new Dimension(width, height), destStrideInBytes, destIsGLOriented, destPixels, dpiX, dpiY); + } + + private static final int getPixelLUMToAny(PixelFormat dest_fmt, ByteBuffer d, int dOff, byte lum, byte alpha) { + switch(dest_fmt) { + case LUMINANCE: + d.put(dOff++, lum); + break; + case BGR888: + case RGB888: + d.put(dOff++, lum); + d.put(dOff++, lum); + d.put(dOff++, lum); + break; + case ABGR8888: + case ARGB8888: + d.put(dOff++, alpha); // A + d.put(dOff++, lum); + d.put(dOff++, lum); + d.put(dOff++, lum); + break; + case BGRA8888: + case RGBA8888: + d.put(dOff++, lum); + d.put(dOff++, lum); + d.put(dOff++, lum); + d.put(dOff++, alpha); // A + break; + default: + throw new InternalError("Unhandled format "+dest_fmt); + } + return dOff; + } + private static final int getPixelRGBA8ToAny(final PixelFormat dest_fmt, final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final boolean srcHasAlpha) { + final int p = PixelFormatUtil.convertToInt32(dest_fmt, (byte)scanline[lineOff], // R + (byte)scanline[lineOff+1], // G + (byte)scanline[lineOff+2], // B + srcHasAlpha ? (byte)scanline[lineOff+3] : (byte)0xff); // A + final int dbpp = dest_fmt.bytesPerPixel(); + d.put(dOff++, (byte) ( p )); // 1 + if( 1 < dbpp ) { + d.put(dOff++, (byte) ( p >>> 8 )); // 2 + d.put(dOff++, (byte) ( p >>> 16 )); // 3 + if( 4 == dbpp ) { + d.put(dOff++, (byte) ( p >>> 24 )); // 4 + } + } + return dOff; + } + private static final int getPixelRGBSame(final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final int bpp) { + d.put(dOff++, (byte)scanline[lineOff]); // R + if( 1 < bpp ) { + d.put(dOff++, (byte)scanline[lineOff + 1]); // G + d.put(dOff++, (byte)scanline[lineOff + 2]); // B + if( 4 == bpp ) { + d.put(dOff++, (byte)scanline[lineOff + 3]); // A + } + } + return dOff; + } + private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer d, final int dOff, final int bytesPerPixel, final boolean hasAlpha) { + final int b = hasAlpha ? 4-1 : 3-1; + if( d.limit() <= dOff + b ) { + throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d); + } + final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, d, dOff); + line.scanline[lineOff ] = 0xff & p; // R + line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G + line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B + if(hasAlpha) { + line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A + } + return dOff + pixelformat.bytesPerPixel(); + } + + /** + * Creates a PNGPixelRect from data supplied by the end user. Shares + * data with the passed ByteBuffer. + * + * @param pixelformat + * @param size + * @param strideInBytes + * @param isGLOriented see {@link #isGLOriented()}. + * @param pixels + * @param dpiX + * @param dpiY + */ + public PNGPixelRect(final PixelFormat pixelformat, final DimensionImmutable size, + final int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels, + final double dpiX, final double dpiY) { + super(pixelformat, size, strideInBytes, isGLOriented, pixels); + this.dpi = new double[] { dpiX, dpiY }; + } + public PNGPixelRect(final PixelRectangle src, final double dpiX, final double dpiY) { + super(src); + this.dpi = new double[] { dpiX, dpiY }; + } + private final double[] dpi; + + /** Returns the dpi of the image. */ + public double[] getDpi() { return dpi; } + + public void write(final OutputStream outstream, final boolean closeOutstream) throws IOException { + final int width = size.getWidth(); + final int height = size.getHeight(); + final int bytesPerPixel = pixelformat.bytesPerPixel(); + final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */, + (4 == bytesPerPixel) ? true : false /* alpha */, + (1 == bytesPerPixel) ? true : false /* grayscale */, + false /* indexed */); + + // open image for writing to a output stream + try { + final PngWriter png = new PngWriter(outstream, imi); + // add some optional metadata (chunks) + png.getMetadata().setDpi(dpi[0], dpi[1]); + png.getMetadata().setTimeNow(0); // 0 seconds fron now = now + png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect"); + // png.getMetadata().setText("my key", "my text"); + final boolean hasAlpha = 4 == bytesPerPixel; + + final ImageLine l1 = new ImageLine(imi); + for (int row = 0; row < height; row++) { + int dataOff = isGLOriented ? ( height - 1 - row ) * strideInBytes : row * strideInBytes; + int lineOff = 0; + if(1 == bytesPerPixel) { + for (int j = width - 1; j >= 0; j--) { + l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel + } + } else { + for (int j = width - 1; j >= 0; j--) { + dataOff = setPixelRGBA8(l1, lineOff, pixels, dataOff, bytesPerPixel, hasAlpha); + lineOff += bytesPerPixel; + } + } + png.writeRow(l1, row); + } + png.end(); + } finally { + if( closeOutstream ) { + IOUtil.close(outstream, false); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index 67ab5176d..0cde24db4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -41,10 +41,12 @@ package com.jogamp.opengl.util.texture; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.URL; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -52,9 +54,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GL2; -import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2GL3; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; @@ -63,11 +66,11 @@ import javax.media.opengl.GLProfile; import jogamp.opengl.Debug; import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; import com.jogamp.opengl.util.texture.spi.DDSImage; import com.jogamp.opengl.util.texture.spi.JPEGImage; import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter; -import com.jogamp.opengl.util.texture.spi.PNGImage; import com.jogamp.opengl.util.texture.spi.SGIImage; import com.jogamp.opengl.util.texture.spi.TGAImage; import com.jogamp.opengl.util.texture.spi.TextureProvider; @@ -1166,27 +1169,29 @@ public class TextureIO { boolean mipmap, String fileSuffix) throws IOException { if (PNG.equals(fileSuffix)) { - PNGImage image = PNGImage.read(/*glp, */ stream); - if (pixelFormat == 0) { - pixelFormat = image.getGLFormat(); - } - if (internalFormat == 0) { + final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); + final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp); + if ( 0 == pixelFormat ) { + pixelFormat = glpa.format; + } // else FIXME: Actually not supported w/ preset pixelFormat! + if ( 0 == internalFormat ) { + final boolean hasAlpha = 4 == glpa.bytesPerPixel; if(glp.isGL2ES3()) { - internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8; + internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; } else { - internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; } } return new TextureData(glp, internalFormat, - image.getWidth(), - image.getHeight(), + image.getSize().getWidth(), + image.getSize().getHeight(), 0, pixelFormat, - image.getGLType(), + glpa.type, mipmap, false, false, - image.getData(), + image.getPixels(), null); } @@ -1392,29 +1397,7 @@ public class TextureIO { final int pixelFormat = pixelAttribs.format; final int pixelType = pixelAttribs.type; final int bytesPerPixel = pixelAttribs.bytesPerPixel; - final boolean reversedChannels; - switch(pixelFormat) { - case GL.GL_ALPHA: - case GL.GL_LUMINANCE: - case GL2ES2.GL_RED: - reversedChannels=false; - break; - case GL.GL_RGB: - reversedChannels=false; - break; - case GL.GL_RGBA: - reversedChannels=false; - break; - case GL2.GL_BGR: - reversedChannels=true; - break; - case GL.GL_BGRA: - reversedChannels=true; - break; - default: - reversedChannels=false; - break; - } + final PixelFormat pixFmt = pixelAttribs.getPixelFormat(); if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) && ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) { ByteBuffer buf = (ByteBuffer) data.getBuffer(); @@ -1423,9 +1406,11 @@ public class TextureIO { } buf.rewind(); - PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f, - bytesPerPixel, reversedChannels, !data.getMustFlipVertically(), buf); - image.write(file, true); + final PNGPixelRect image = new PNGPixelRect(pixFmt, new Dimension(data.getWidth(), data.getHeight()), + 0 /* stride */, true /* isGLOriented */, buf /* pixels */, + -1f, -1f); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */)); + image.write(outs, true /* close */); return true; } throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+ diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java deleted file mode 100644 index 71cbbf97e..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java +++ /dev/null @@ -1,319 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.util.texture.spi; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -import javax.media.opengl.GL; - -import jogamp.opengl.Debug; -import jogamp.opengl.util.pngj.ImageInfo; -import jogamp.opengl.util.pngj.ImageLine; -import jogamp.opengl.util.pngj.ImageLineHelper; -import jogamp.opengl.util.pngj.PngReader; -import jogamp.opengl.util.pngj.PngWriter; -import jogamp.opengl.util.pngj.chunks.PngChunkPLTE; -import jogamp.opengl.util.pngj.chunks.PngChunkTRNS; -import jogamp.opengl.util.pngj.chunks.PngChunkTextVar; - -import com.jogamp.common.nio.Buffers; -import com.jogamp.common.util.IOUtil; - -public class PNGImage { - private static final boolean DEBUG = Debug.debug("PNGImage"); - - /** - * Creates a PNGImage from data supplied by the end user. Shares - * data with the passed ByteBuffer. Assumes the data is already in - * the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA. - * Orientation is bottom-to-top (OpenGL coord. default) - * or top-to-bottom depending on isGLOriented. - * - * @param width - * @param height - * @param dpiX - * @param dpiY - * @param bytesPerPixel - * @param reversedChannels - * @param isGLOriented see {@link #isGLOriented()}. - * @param data - * @return - */ - public static PNGImage createFromData(int width, int height, double dpiX, double dpiY, - int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) { - return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, isGLOriented, data); - } - - /** - * Reads a PNG image from the specified InputStream. - *

    - * Implicitly flip image to GL orientation, see {@link #isGLOriented()}. - *

    - */ - public static PNGImage read(InputStream in) throws IOException { - return new PNGImage(in); - } - - /** Reverse read and store, implicitly flip image to GL orientation, see {@link #isGLOriented()}. */ - private static final int getPixelRGBA8(ByteBuffer d, int dOff, int[] scanline, int lineOff, boolean hasAlpha) { - final int b = hasAlpha ? 4-1 : 3-1; - if( d.limit() <= dOff || dOff - b < 0 ) { - throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+(dOff-b)+".."+dOff+"]: "+d); - } - if(hasAlpha) { - d.put(dOff--, (byte)scanline[lineOff + 3]); // A - } - d.put(dOff--, (byte)scanline[lineOff + 2]); // B - d.put(dOff--, (byte)scanline[lineOff + 1]); // G - d.put(dOff--, (byte)scanline[lineOff ]); // R - return dOff; - } - - /** Reverse write and store, implicitly flip image from current orientation, see {@link #isGLOriented()}. Handle reversed channels (BGR[A]). */ - private int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha) { - final int b = hasAlpha ? 4-1 : 3-1; - if( d.limit() <= dOff + b ) { - throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d); - } - if( reversedChannels ) { - if(hasAlpha) { - line.scanline[lineOff + 3] = d.get(dOff++); // A - } - line.scanline[lineOff + 2] = d.get(dOff++); // R - line.scanline[lineOff + 1] = d.get(dOff++); // G - line.scanline[lineOff ] = d.get(dOff++); // B - } else { - line.scanline[lineOff ] = d.get(dOff++); // R - line.scanline[lineOff + 1] = d.get(dOff++); // G - line.scanline[lineOff + 2] = d.get(dOff++); // B - if(hasAlpha) { - line.scanline[lineOff + 3] = d.get(dOff++); // A - } - } - return isGLOriented ? dOff - bytesPerPixel - bytesPerPixel : dOff; - } - - private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) { - pixelWidth=width; - pixelHeight=height; - dpi = new double[] { dpiX, dpiY }; - if(4 == bytesPerPixel) { - glFormat = GL.GL_RGBA; - } else if (3 == bytesPerPixel) { - glFormat = GL.GL_RGB; - } else { - throw new InternalError("XXX: bytesPerPixel "+bytesPerPixel); - } - this.bytesPerPixel = bytesPerPixel; - this.reversedChannels = reversedChannels; - this.isGLOriented = isGLOriented; - this.data = data; - } - - private PNGImage(InputStream in) { - final PngReader pngr = new PngReader(new BufferedInputStream(in), null); - final ImageInfo imgInfo = pngr.imgInfo; - final PngChunkPLTE plte = pngr.getMetadata().getPLTE(); - final PngChunkTRNS trns = pngr.getMetadata().getTRNS(); - final boolean indexed = imgInfo.indexed; - final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ; - - final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ; - if ( ! ( 1 == channels || 3 == channels || 4 == channels ) ) { - throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels + " Paletted: " + indexed); - } - - bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ; - if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel ) ) { - throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel); - } - if( channels != bytesPerPixel ) { - throw new RuntimeException("PNGImage currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel); - } - pixelWidth = imgInfo.cols; - pixelHeight = imgInfo.rows; - dpi = new double[2]; - { - final double[] dpi2 = pngr.getMetadata().getDpi(); - dpi[0]=dpi2[0]; - dpi[1]=dpi2[1]; - } - if ( indexed ) { - if ( hasAlpha ) { - glFormat = GL.GL_RGBA; - } else { - glFormat = GL.GL_RGB; - } - } else { - switch( channels ) { - case 1: glFormat = GL.GL_LUMINANCE; break; - case 3: glFormat = GL.GL_RGB; break; - case 4: glFormat = GL.GL_RGBA; break; - default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel); - } - } - if(DEBUG) { - System.err.println("PNGImage: "+imgInfo); - System.err.println("PNGImage: indexed "+indexed+", alpha "+hasAlpha+", channels "+channels+"/"+imgInfo.channels+ - ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+ - ", pixels "+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+"x"+dpi[1]+", glFormat 0x"+Integer.toHexString(glFormat)); - } - - data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight); - reversedChannels = false; // RGB[A] - isGLOriented = true; - int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store - - int[] rgbaScanline = indexed ? new int[imgInfo.cols * channels] : null; - - for (int row = 0; row < pixelHeight; row++) { - final ImageLine l1 = pngr.readRow(row); - int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read (PNG top-left -> OpenGL bottom-left origin) - if( indexed ) { - for (int j = pixelWidth - 1; j >= 0; j--) { - rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized - dataOff = getPixelRGBA8(data, dataOff, rgbaScanline, lineOff, hasAlpha); - lineOff -= bytesPerPixel; - } - } else if( 1 == channels ) { - for (int j = pixelWidth - 1; j >= 0; j--) { - data.put(dataOff--, (byte)l1.scanline[lineOff--]); // Luminance, 1 bytesPerPixel - } - } else { - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = getPixelRGBA8(data, dataOff, l1.scanline, lineOff, hasAlpha); - lineOff -= bytesPerPixel; - } - } - } - pngr.end(); - } - private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel; - private final boolean reversedChannels; - private final boolean isGLOriented; - private final double[] dpi; - private final ByteBuffer data; - - /** Returns the width of the image. */ - public int getWidth() { return pixelWidth; } - - /** Returns the height of the image. */ - public int getHeight() { return pixelHeight; } - - /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */ - public boolean getHasReversedChannels() { return reversedChannels; } - - /** - * Returns true if the drawable is rendered in - * OpenGL's coordinate system, origin at bottom left. - * Otherwise returns false, i.e. origin at top left. - *

    - * Default impl. is true, i.e. OpenGL coordinate system. - *

    - */ - public boolean isGLOriented() { return isGLOriented; } - - /** Returns the dpi of the image. */ - public double[] getDpi() { return dpi; } - - /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */ - public int getGLFormat() { return glFormat; } - - /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */ - public int getGLType() { return GL.GL_UNSIGNED_BYTE; } - - /** Returns the bytes per pixel */ - public int getBytesPerPixel() { return bytesPerPixel; } - - /** Returns the raw data for this texture in the correct - (bottom-to-top) order for calls to glTexImage2D. */ - public ByteBuffer getData() { return data; } - - public void write(File out, boolean allowOverwrite) throws IOException { - final ImageInfo imi = new ImageInfo(pixelWidth, pixelHeight, 8, (4 == bytesPerPixel) ? true : false); // 8 bits per channel, no alpha - // open image for writing to a output stream - final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out, allowOverwrite)); - try { - final PngWriter png = new PngWriter(outs, imi); - // add some optional metadata (chunks) - png.getMetadata().setDpi(dpi[0], dpi[1]); - png.getMetadata().setTimeNow(0); // 0 seconds fron now = now - png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGImage"); - // png.getMetadata().setText("my key", "my text"); - final boolean hasAlpha = 4 == bytesPerPixel; - final ImageLine l1 = new ImageLine(imi); - if( isGLOriented ) { - // start at last pixel at end-of-buffer, reverse read (OpenGL bottom-left -> PNG top-left origin) - int dataOff = ( pixelWidth * bytesPerPixel * ( pixelHeight - 1 ) ) + // full lines - 1 line - ( ( pixelWidth - 1 ) * bytesPerPixel ); // one line - 1 pixel - for (int row = 0; row < pixelHeight; row++) { - int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store (OpenGL bottom-left -> PNG top-left origin) - if(1 == bytesPerPixel) { - for (int j = pixelWidth - 1; j >= 0; j--) { - l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel - } - } else { - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha); - lineOff -= bytesPerPixel; - } - } - png.writeRow(l1, row); - } - } else { - int dataOff = 0; // start at first pixel at start-of-buffer, normal read (same origin: top-left) - for (int row = 0; row < pixelHeight; row++) { - int lineOff = 0; // start w/ first pixel in line, normal store (same origin: top-left) - if(1 == bytesPerPixel) { - for (int j = pixelWidth - 1; j >= 0; j--) { - l1.scanline[lineOff++] = data.get(dataOff++); // // Luminance, 1 bytesPerPixel - } - } else { - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha); - lineOff += bytesPerPixel; - } - } - png.writeRow(l1, row); - } - } - png.end(); - } finally { - IOUtil.close(outs, false); - } - } - - @Override - public String toString() { return "PNGImage["+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+" x "+dpi[1]+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+data+"]"; } -} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index b947505cb..ddf513180 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -38,7 +38,6 @@ package com.jogamp.nativewindow.awt; import com.jogamp.common.os.Platform; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; @@ -53,7 +52,6 @@ import java.awt.event.ComponentListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.applet.Applet; -import java.io.IOException; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -66,6 +64,7 @@ import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.PixelRectangle; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.Rectangle; @@ -433,19 +432,19 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } @Override - public final boolean setCursor(final IOUtil.ClassResources resources, final PointImmutable hotSpot) throws IOException { + public final boolean setCursor(final PixelRectangle pixelrect, final PointImmutable hotSpot) { AWTEDTExecutor.singleton.invoke(false, new Runnable() { public void run() { Cursor c = null; - if( null == resources || null == hotSpot ) { + if( null == pixelrect || null == hotSpot ) { c = Cursor.getDefaultCursor(); } else { final java.awt.Point awtHotspot = new java.awt.Point(hotSpot.getX(), hotSpot.getY()); try { - c = AWTMisc.getCursor(resources, awtHotspot); - } catch (IOException e) { - e.printStackTrace(); - } + c = AWTMisc.getCursor(pixelrect, awtHotspot); + } catch (Exception e) { + e.printStackTrace(); + } } if( null != c ) { component.setCursor(c); @@ -455,7 +454,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } @Override - public boolean hideCursor() { + public final boolean hideCursor() { AWTEDTExecutor.singleton.invoke(false, new Runnable() { public void run() { component.setCursor(AWTMisc.getNullCursor()); diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index 81983a7c2..cf8cf89d2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -27,11 +27,9 @@ */ package javax.media.nativewindow; -import java.io.IOException; - +import javax.media.nativewindow.util.PixelRectangle; import javax.media.nativewindow.util.PointImmutable; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.locks.RecursiveLock; /** @@ -73,12 +71,12 @@ public interface OffscreenLayerSurface { /** * Optional method setting cursor in the corresponding on-screen surface/window, if exists. * - * @param resources maybe null for default cursor + * @param pixelrect cursor pixels, maybe null for default cursor * @param hotSpot maybe null for default cursor * @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false. - * @throws IOException */ - public boolean setCursor(IOUtil.ClassResources resources, PointImmutable hotSpot) throws IOException; + public boolean setCursor(PixelRectangle pixelrect, PointImmutable hotSpot); + /** * Optional method hiding the cursor in the corresponding on-screen surface/window, if exists. * diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java index b690aff4d..069cffeb8 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java +++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java @@ -37,21 +37,19 @@ import java.awt.Component; import java.awt.Container; import java.awt.Frame; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.net.URLConnection; import java.util.HashMap; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JRootPane; import javax.swing.WindowConstants; -import javax.imageio.ImageIO; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.util.PixelRectangle; +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelFormatUtil; import javax.swing.MenuSelectionManager; -import com.jogamp.common.util.IOUtil; - public class AWTMisc { public static JFrame getJFrame(Component c) { @@ -173,7 +171,7 @@ public class AWTMisc { MenuSelectionManager.defaultManager().clearSelectedPath(); } - static final HashMap cursorMap = new HashMap(); + static final HashMap cursorMap = new HashMap(); static final Cursor nulCursor; static { final Toolkit toolkit = Toolkit.getDefaultToolkit(); @@ -183,21 +181,43 @@ public class AWTMisc { public static synchronized Cursor getNullCursor() { return nulCursor; } - public static synchronized Cursor getCursor(IOUtil.ClassResources resources, Point hotSpot) throws IOException { - final String key = resources.getClass().getName()+":"+resources.resourcePaths[0]; + public static synchronized Cursor getCursor(PixelRectangle pixelrect, Point hotSpot) { + // 31 * x == (x << 5) - x + int hash = 31 + pixelrect.hashCode(); + hash = ((hash << 5) - hash) + hotSpot.hashCode(); + final Integer key = Integer.valueOf(hash); + Cursor cursor = cursorMap.get(key); if( null == cursor ) { - cursor = createAWTCursor(resources, hotSpot); + cursor = createCursor(pixelrect, hotSpot); cursorMap.put(key, cursor); } return cursor; } - private static synchronized Cursor createAWTCursor(IOUtil.ClassResources resources, Point hotSpot) throws IOException { - final URLConnection urlConn = resources.resolve(0); - final BufferedImage img = ImageIO.read(urlConn.getInputStream()); - + private static synchronized Cursor createCursor(PixelRectangle pixelrect, Point hotSpot) { + final int width = pixelrect.getSize().getWidth(); + final int height = pixelrect.getSize().getHeight(); + final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888 + final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() { + public void store(int x, int y, int pixel) { + img.setRGB(x, y, pixel); + } + @Override + public final PixelFormat getPixelformat() { + return PixelFormat.BGRA8888; + } + @Override + public int getStride() { + return width*4; + } + @Override + public final boolean isGLOriented() { + return false; + } + }; + PixelFormatUtil.convert32(imgSink, pixelrect); final Toolkit toolkit = Toolkit.getDefaultToolkit(); - return toolkit.createCustomCursor(img, hotSpot, resources.resourcePaths[0]); + return toolkit.createCustomCursor(img, hotSpot, pixelrect.toString()); } public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(int awtClosingOperation) { diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 8d1445f80..4b38fcca5 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -30,14 +30,14 @@ package com.jogamp.newt; import java.io.IOException; import java.lang.ref.WeakReference; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PixelRectangle; +import javax.media.nativewindow.util.PixelFormat; import javax.media.nativewindow.util.PointImmutable; import jogamp.newt.Debug; @@ -47,6 +47,7 @@ import com.jogamp.newt.util.EDTUtil; public abstract class Display { public static final boolean DEBUG = Debug.debug("Display"); + protected static final boolean DEBUG_POINTER_ICON = Debug.debug("Display.PointerIcon"); /** return precomputed hashCode from FQN {@link #getFQName()} */ @Override @@ -66,7 +67,9 @@ public abstract class Display { /** * Native PointerIcon handle. *

    - * Instances can be created via {@link Display}'s {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(..)}. + * Instances can be created via {@link Display}'s + * {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(pngResource, ..)} + * or {@link Display#createPointerIcon(PixelRectangle, int, int) createPointerIcon(pixelrect, ..)}. *

    *

    * Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed. @@ -75,23 +78,65 @@ public abstract class Display { * Instance can be re-validated after destruction via {@link #validate()}. *

    *

    + * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use! + *

    + *

    * {@link PointerIcon} may be {@link #destroy() destroyed} manually after use, * i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore. + * However, this is not required. *

    *

    * PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}. *

    */ - public static interface PointerIcon { + public static interface PointerIcon extends PixelRectangle { /** - * @return the associated Display + * Always neatly packed, i.e. width * bytes_per_pixel. + *

    + * {@inheritDoc} + *

    */ - Display getDisplay(); + @Override + int getStride(); + + /** + * Always false, i.e. origin is TOP-LEFT. + *

    + * {@inheritDoc} + *

    + */ + boolean isGLOriented(); + + /** + * Computes a hash code over: + *
      + *
    • display
    • + *
    • pixelformat
    • + *
    • size
    • + *
    • stride
    • + *
    • isGLOriented
    • + *
    • pixels
    • + *
    • hotspot
    • + *
    + * Dismissing the native handle! + *

    + * The hashCode shall be computed only once with first call + * and stored for later retrieval to enhance performance. + *

    + *

    + * {@inheritDoc} + *

    + */ + @Override + int hashCode(); /** - * @return the single {@link IOUtil.ClassResources}. + * @return the associated Display */ - IOUtil.ClassResources getResource(); + Display getDisplay(); + + /** Returns the hotspot. */ + PointImmutable getHotspot(); /** * Returns true if valid, otherwise false. @@ -116,35 +161,69 @@ public abstract class Display { *

    */ void destroy(); + } - /** Returns the size, i.e. width and height. */ - DimensionImmutable getSize(); + /** + * Returns the native platform's {@link PointerIcon.PixelFormat} for pointer-icon pixel data. + *

    + * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}. + *

    + */ + public abstract PixelFormat getNativePointerIconPixelFormat(); - /** Returns the hotspot. */ - PointImmutable getHotspot(); + /** + * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data. + *

    + * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}. + *

    + */ + public abstract boolean getNativePointerIconForceDirectNIO(); - @Override - String toString(); - } + /** + * Returns the newly created {@link PointerIcon} or null if not implemented on platform. + *

    + * See {@link PointerIcon} for lifecycle semantics. + *

    + * + * @param pngResource single PNG resource for the {@link PointerIcon}. Only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used. + * @param hotX pointer hotspot x-coord, origin is upper-left corner + * @param hotY pointer hotspot y-coord, origin is upper-left corner + * + * @throws IllegalArgumentException if pngResource is null or invalid + * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}. + * @throws IOException if the pngResource could not be {@link IOUtil.ClassResources#resolve(int) resolved} + * or via the PNG parser processing the input stream. + * + * @see PointerIcon + * @see Window#setPointerIcon(PointerIcon) + */ + public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) + throws IllegalArgumentException, IllegalStateException, IOException; /** * Returns the newly created {@link PointerIcon} or null if not implemented on platform. *

    * See {@link PointerIcon} for lifecycle semantics. *

    + *

    + * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()} + * is not matched by the given pixelrect, the pixelrect is converted + * into the required {@link PixelFormat} and NIO type. + *

    * - * @param pngResource single PNG resource, only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used. + * @param pixelrect {@link PixelRectangle} source for the {@link PointerIcon} * @param hotX pointer hotspot x-coord, origin is upper-left corner * @param hotY pointer hotspot y-coord, origin is upper-left corner + * + * @throws IllegalArgumentException if pixelrect is null. * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}. - * @throws MalformedURLException - * @throws InterruptedException - * @throws IOException * * @see PointerIcon * @see Window#setPointerIcon(PointerIcon) + * @see #getNativePointerIconPixelFormat() + * @see #getNativePointerIconForceDirectNIO() */ - public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws IllegalStateException, MalformedURLException, InterruptedException, IOException; + public abstract PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) throws IllegalArgumentException, IllegalStateException; /** * Manual trigger the native creation, if it is not done yet.
    diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java index 7ffbc2e83..472672fd9 100644 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java @@ -235,10 +235,10 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { glWindow.setVisible(true); glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); if( null == pointerIconTest ) { - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } ); final Display disp = glWindow.getScreen().getDisplay(); try { - pointerIconTest = disp.createPointerIcon(res, 16, 0); + pointerIconTest = disp.createPointerIcon(res, 16, 16); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index 346c03b15..4c7169ec4 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -34,7 +34,9 @@ package jogamp.newt; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.ReflectionUtil; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.NEWTEvent; @@ -43,17 +45,25 @@ import com.jogamp.newt.event.NEWTEventConsumer; import jogamp.newt.event.NEWTEventTask; import com.jogamp.newt.util.EDTUtil; +import com.jogamp.opengl.util.PNGPixelRect; import java.io.IOException; -import java.net.MalformedURLException; +import java.net.URLConnection; +import java.nio.ByteBuffer; import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.util.PixelFormatUtil; +import javax.media.nativewindow.util.PixelRectangle; +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; public abstract class DisplayImpl extends Display { private static int serialno = 1; + private static final boolean pngUtilAvail; static { NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() { @@ -64,8 +74,14 @@ public abstract class DisplayImpl extends Display { DisplayImpl.shutdownAll(); } }); + + final ClassLoader cl = DisplayImpl.class.getClassLoader(); + pngUtilAvail = ReflectionUtil.isClassAvailable("jogamp.opengl.util.pngj.PngReader", cl) && + ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl); } + public static final boolean isPNGUtilAvailable() { return pngUtilAvail; } + final ArrayList pointerIconList = new ArrayList(); /** Executed from EDT! */ @@ -86,13 +102,94 @@ public abstract class DisplayImpl extends Display { } @Override - public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { - return createPointerIcon(false /* isTemp */, pngResource, hotX, hotY); + public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; } + @Override + public boolean getNativePointerIconForceDirectNIO() { return false; } + + @Override + public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) + throws IllegalArgumentException, IllegalStateException, IOException + { + if( !isNativeValid() ) { + throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this); + } + if( null == pngResource || 0 >= pngResource.resourceCount() ) { + throw new IllegalArgumentException("Null or invalid pngResource "+pngResource); + } + if( !pngUtilAvail ) { + return null; + } + final PointerIconImpl[] res = { null }; + runOnEDTIfAvail(true, new Runnable() { + public void run() { + try { + if( !DisplayImpl.this.isNativeValid() ) { + throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this); + } + final URLConnection urlConn = pngResource.resolve(0); + if( null == urlConn ) { + throw new IOException("Could not resolve "+pngResource.resourcePaths[0]); + } + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), + getNativePointerIconPixelFormat(), + getNativePointerIconForceDirectNIO(), + 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + final long handle = createPointerIconImplChecked(image.getPixelformat(), image.getSize().getWidth(), image.getSize().getHeight(), + image.getPixels(), hotX, hotY); + final PointImmutable hotspot = new Point(hotX, hotY); + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot); + } + if( 0 != handle ) { + res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle); + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconPNG.0: "+res[0]); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } } ); + if( null != res[0] ) { + synchronized(pointerIconList) { + pointerIconList.add(res[0]); + } + } + return res[0]; } - PointerIcon createPointerIcon(final boolean isTemp, final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { + + @Override + public final PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) + throws IllegalArgumentException, IllegalStateException + { if( !isNativeValid() ) { throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this); } + if( null == pixelrect ) { + throw new IllegalArgumentException("Null or pixelrect"); + } + final PixelRectangle fpixelrect; + if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) { + // conversion ! + fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(), + 0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() ); + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect); + } + } else if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixelrect.getPixels()) ) { + // transfer to direct NIO + final ByteBuffer sBB = pixelrect.getPixels(); + final ByteBuffer dBB = Buffers.newDirectByteBuffer(sBB.array(), sBB.arrayOffset()); + fpixelrect = new PixelRectangle.GenericPixelRect(pixelrect.getPixelformat(), pixelrect.getSize(), pixelrect.getStride(), pixelrect.isGLOriented(), dBB); + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconRES.0: Conversion-NIO "+pixelrect+" -> "+fpixelrect); + } + } else { + fpixelrect = pixelrect; + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconRES.0: No conversion "+fpixelrect); + } + } final PointerIconImpl[] res = { null }; runOnEDTIfAvail(true, new Runnable() { public void run() { @@ -100,22 +197,63 @@ public abstract class DisplayImpl extends Display { if( !DisplayImpl.this.isNativeValid() ) { throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this); } - res[0] = createPointerIconImpl(pngResource, hotX, hotY); + if( null != fpixelrect ) { + final long handle = createPointerIconImplChecked(fpixelrect.getPixelformat(), + fpixelrect.getSize().getWidth(), + fpixelrect.getSize().getHeight(), + fpixelrect.getPixels(), hotX, hotY); + if( 0 != handle ) { + res[0] = new PointerIconImpl(DisplayImpl.this, fpixelrect, new Point(hotX, hotY), handle); + } + } } catch (Exception e) { e.printStackTrace(); } } } ); - if( !isTemp ) { + if( null != res[0] ) { synchronized(pointerIconList) { pointerIconList.add(res[0]); } } return res[0]; } - /** Executed from EDT! */ - protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { - return null; + + /** + * Executed from EDT! + * + * @param pixelformat the pixels's format + * @param width the pixels's width + * @param height the pixels's height + * @param pixels the pixels + * @param hotX the PointerIcon's hot-spot x-coord + * @param hotY the PointerIcon's hot-spot x-coord + * @return if successful a valid handle (not null), otherwise null. + */ + protected final long createPointerIconImplChecked(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) { + if( getNativePointerIconPixelFormat() != pixelformat ) { + throw new IllegalArgumentException("Pixelformat no "+getNativePointerIconPixelFormat()+", but "+pixelformat); + } + if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixels) ) { + throw new IllegalArgumentException("pixel buffer is not direct "+pixels); + } + return createPointerIconImpl(pixelformat, width, height, pixels, hotX, hotY); + } + + /** + * Executed from EDT! + * + * @param pixelformat the pixels's format + * @param width the pixels's width + * @param height the pixels's height + * @param pixels the pixels + * @param hotX the PointerIcon's hot-spot x-coord + * @param hotY the PointerIcon's hot-spot x-coord + * @return if successful a valid handle (not null), otherwise null. + */ + protected long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) { + return 0; } + /** Executed from EDT! */ protected void destroyPointerIconImpl(final long displayHandle, long piHandle) { } diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java index e2388be67..7c8535f20 100644 --- a/src/newt/classes/jogamp/newt/PointerIconImpl.java +++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java @@ -27,27 +27,63 @@ */ package jogamp.newt; +import java.nio.ByteBuffer; + import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelRectangle; import javax.media.nativewindow.util.PointImmutable; -import com.jogamp.common.util.IOUtil; -import com.jogamp.common.util.IOUtil.ClassResources; import com.jogamp.newt.Display; import com.jogamp.newt.Display.PointerIcon; public class PointerIconImpl implements PointerIcon { private final DisplayImpl display; - private final IOUtil.ClassResources resource; + private final PixelFormat pixelformat; private final DimensionImmutable size; + private final ByteBuffer pixels; private final PointImmutable hotspot; private long handle; - public PointerIconImpl(DisplayImpl display, ClassResources resource, final DimensionImmutable size, final PointImmutable hotspot, final long handle) { + private int hashCode = 0; + private volatile boolean hashCodeComputed = false; + + public PointerIconImpl(final DisplayImpl display, final PixelFormat pixelformat, final DimensionImmutable size, final ByteBuffer pixels, final PointImmutable hotspot, final long handle) { this.display = display; - this.resource = resource; + this.pixelformat = pixelformat; this.size = size; + this.pixels = pixels; this.hotspot = hotspot; + this.handle=handle; } + public PointerIconImpl(final DisplayImpl display, final PixelRectangle pixelrect, final PointImmutable hotspot, final long handle) { + this.display = display; + this.pixelformat = pixelrect.getPixelformat(); + this.size = pixelrect.getSize(); + this.pixels = pixelrect.getPixels(); + this.hotspot = hotspot; + this.handle=handle; + } + + @Override + public int hashCode() { + if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE + synchronized (this) { + if( !hashCodeComputed ) { + // 31 * x == (x << 5) - x + int hash = 31 + display.getFQName().hashCode(); + hash = ((hash << 5) - hash) + pixelformat.hashCode(); + hash = ((hash << 5) - hash) + size.hashCode(); + hash = ((hash << 5) - hash) + getStride(); + hash = ((hash << 5) - hash) + ( isGLOriented() ? 1 : 0); + hash = ((hash << 5) - hash) + pixels.hashCode(); + hashCode = ((hash << 5) - hash) + hotspot.hashCode(); + } + } + } + return hashCode; + } + public synchronized final long getHandle() { return handle; } public synchronized final long validatedHandle() { synchronized(display.pointerIconList) { @@ -57,8 +93,7 @@ public class PointerIconImpl implements PointerIcon { } if( 0 == handle ) { try { - final PointerIconImpl temp = (PointerIconImpl) display.createPointerIcon(true /* isTemp */, resource, hotspot.getX(), hotspot.getY()); - handle = temp.handle; + handle = display.createPointerIconImpl(pixelformat, size.getWidth(), size.getHeight(), pixels, hotspot.getX(), hotspot.getY()); return handle; } catch (Exception e) { e.printStackTrace(); @@ -71,7 +106,9 @@ public class PointerIconImpl implements PointerIcon { @Override public final Display getDisplay() { return display; } @Override - public final IOUtil.ClassResources getResource() { return resource; } + public final PixelFormat getPixelformat() { return pixelformat; } + @Override + public final ByteBuffer getPixels() { return pixels; } @Override public synchronized final boolean isValid() { return 0 != handle; } @Override @@ -116,11 +153,19 @@ public class PointerIconImpl implements PointerIcon { return size; } @Override + public final int getStride() { + return size.getWidth() * pixelformat.bytesPerPixel(); + } + @Override + public final boolean isGLOriented() { + return false; + } + @Override public final PointImmutable getHotspot() { return hotspot; } @Override public final String toString() { - return "PointerIcon["+DisplayImpl.toHexString(super.hashCode())+", "+display.getFQName()+", "+resource.resourcePaths[0]+", 0x"+Long.toHexString(handle)+", "+size+", "+hotspot+"]"; + return "PointerIcon[obj 0x"+Integer.toHexString(super.hashCode())+", "+display.getFQName()+", 0x"+Long.toHexString(handle)+", "+pixelformat+", "+size+", "+hotspot+", pixels "+pixels+"]"; } } \ No newline at end of file diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 50f30f04d..dc9affd63 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -53,6 +53,7 @@ import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.PixelRectangle; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.Rectangle; @@ -61,7 +62,6 @@ import javax.media.nativewindow.util.RectangleImmutable; import jogamp.nativewindow.SurfaceUpdatedHelper; import com.jogamp.common.util.ArrayHashSet; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.IntBitfield; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.locks.LockFactory; @@ -1700,7 +1700,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } /** * Helper method to delegate {@link #setPointerVisibleImpl(boolean)} to - * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}. + * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}. *

    * Note: JAWTWindow is an OffscreenLayerSurface. *

    @@ -1755,7 +1755,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } /** * Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to - * {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}. + * {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)} *

    * Note: JAWTWindow is an OffscreenLayerSurface. *

    @@ -1777,7 +1777,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent; try { if( null != pi ) { - return ols.setCursor(pi.getResource(), pi.getHotspot()); + return ols.setCursor(pi, pi.getHotspot()); } else { return ols.setCursor(null, null); // default } diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java index ffa62978f..967acd413 100644 --- a/src/newt/classes/jogamp/newt/driver/PNGIcon.java +++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java @@ -32,6 +32,7 @@ import java.net.MalformedURLException; import java.nio.ByteBuffer; import jogamp.newt.Debug; +import jogamp.newt.DisplayImpl; import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.ReflectionUtil; @@ -45,8 +46,7 @@ public class PNGIcon { Debug.initSingleton(); final ClassLoader cl = PNGIcon.class.getClassLoader(); - avail = ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl) && - ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.texture.spi.PNGImage", cl); + avail = DisplayImpl.isPNGUtilAvailable() && ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl); } /** Returns true if PNG decoder is available. */ @@ -55,7 +55,11 @@ public class PNGIcon { } /** - * Implemented for X11. + * Special implementation for X11 Window Icons + *

    + * The returned byte buffer is a direct buffer! + *

    + * * @param resources * @param data_size * @param elem_bytesize @@ -73,29 +77,4 @@ public class PNGIcon { } throw new UnsupportedOperationException(err0); } - - /** - * Implemented for Windows. - * @param resources - * @param toBGRA if true, arranges stores in BGRA888 order, otherwise RGBA888 - * @param width - * @param height - * @param data_size - * @param resourcesIdx - * @return pixels with origin at upper-left corner. - * If storing RGBA8888, component R is located on the lowest 8-bit. - * If storing BGRA8888, component B is located on the lowest 8-bit. - * Component A is located on the highest 8-bit. - * - * @throws UnsupportedOperationException if not implemented - * @throws InterruptedException - * @throws IOException - * @throws MalformedURLException - */ - public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException { - if( avail ) { - return jogamp.newt.driver.opengl.JoglUtilPNGIcon.singleToRGBAImage(resources, resourceIdx, toBGRA, width, height, data_size); - } - throw new UnsupportedOperationException(err0); - } } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java index 30583c48c..d850a18af 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -34,28 +34,25 @@ package jogamp.newt.driver.macosx; -import java.io.IOException; -import java.net.MalformedURLException; +import java.net.URLConnection; import java.nio.Buffer; import java.nio.ByteBuffer; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PixelFormat; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.newt.NewtFactory; +import com.jogamp.opengl.util.PNGPixelRect; import jogamp.newt.DisplayImpl; import jogamp.newt.NEWTJNILibLoader; -import jogamp.newt.PointerIconImpl; -import jogamp.newt.driver.PNGIcon; public class DisplayDriver extends DisplayImpl { - private static final int defaultIconWidth, defaultIconHeight; - private static final Buffer defaultIconData; + private static final PNGPixelRect defaultIconData; static { NEWTJNILibLoader.loadNEWT(); @@ -67,21 +64,23 @@ public class DisplayDriver extends DisplayImpl { throw new NativeWindowException("Failed to initialize jmethodIDs"); } { - final int[] width = { 0 }, height = { 0 }, data_size = { 0 }; - Buffer data=null; - if( PNGIcon.isAvailable() ) { + PNGPixelRect image=null; + if( DisplayImpl.isPNGUtilAvailable() ) { try { + // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly! final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons(); - data = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, false /* toBGRA */, width, height, data_size); + final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1); + image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); } catch (Exception e) { e.printStackTrace(); } } - defaultIconWidth = width[0]; - defaultIconHeight = height[0]; - defaultIconData = data; + defaultIconData = image; if( null != defaultIconData ) { - DisplayDriver.setAppIcon0(defaultIconData, defaultIconWidth, defaultIconHeight); + final Buffer pixels = defaultIconData.getPixels(); + DisplayDriver.setAppIcon0( + pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */, + defaultIconData.getSize().getWidth(), defaultIconData.getSize().getHeight()); } } @@ -112,17 +111,20 @@ public class DisplayDriver extends DisplayImpl { aDevice.close(); } + /** + * {@inheritDoc} + *

    + * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly! + *

    + */ @Override - protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException { - if( PNGIcon.isAvailable() ) { - final int[] width = { 0 }, height = { 0 }, data_size = { 0 }; - if( null != pngResource && 0 < pngResource.resourceCount() ) { - final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size); - return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]), - new Point(hotX, hotY), createPointerIcon0(data, width[0], height[0], hotX, hotY)); - } - } - return null; + public final boolean getNativePointerIconForceDirectNIO() { return true; } + + @Override + protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) { + return createPointerIcon0( + pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */, + width, height, hotX, hotY); } @Override @@ -140,8 +142,8 @@ public class DisplayDriver extends DisplayImpl { private static native boolean initNSApplication0(); private static native void runNSApplication0(); private static native void stopNSApplication0(); - /* pp */ static native void setAppIcon0(Object iconData, int iconWidth, int iconHeight); - private static native long createPointerIcon0(Object iconData, int iconWidth, int iconHeight, int hotX, int hotY); + /* pp */ static native void setAppIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height); + private static native long createPointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY); private static native long destroyPointerIcon0(long handle); } diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java index 216a0cb20..551929b8d 100644 --- a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java +++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java @@ -32,20 +32,22 @@ import java.net.MalformedURLException; import java.net.URLConnection; import java.nio.ByteBuffer; +import javax.media.nativewindow.util.PixelFormat; + import com.jogamp.common.nio.Buffers; import com.jogamp.common.os.Platform; import com.jogamp.common.util.IOUtil; -import com.jogamp.opengl.util.texture.spi.PNGImage; +import com.jogamp.opengl.util.PNGPixelRect; public class JoglUtilPNGIcon { public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException { - final PNGImage[] images = new PNGImage[resources.resourceCount()]; + final PNGPixelRect[] images = new PNGPixelRect[resources.resourceCount()]; data_size[0] = 0; for(int i=0; iGetDirectBufferAddress(env, jiconData); +static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) { + if( NULL != iconData ) { NSInteger iconWidth = (NSInteger) jiconWidth; NSInteger iconHeight = (NSInteger) jiconHeight; const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp; @@ -319,28 +318,47 @@ static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jico * Method: setAppIcon0 */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0 - (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight) + (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height) { + if( 0 == pixels ) { + return; + } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); + // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly! + unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); + NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height); if( NULL != nsImage ) { [nsImage autorelease]; [NSApp setApplicationIconImage: nsImage]; } + if ( JNI_FALSE == pixels_is_direct ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } [pool release]; } JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0 - (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight, jint hotX, jint hotY) + (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY) { + if( 0 == pixels ) { + return 0; + } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight); + unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); + NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height); NSCursor * res = NULL; if( NULL != nsImage ) { [nsImage autorelease]; NSPoint hotP = { hotX, hotY }; res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; } + if ( JNI_FALSE == pixels_is_direct ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } [pool release]; DBG_PRINT( "createPointerIcon0 %p\n", res); return (jlong) (intptr_t) res; diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 1fd8d0039..c20e156c1 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -2368,9 +2368,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0 JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused, - jobject data, jint data_offset, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) { + jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) { - const unsigned char * data_ptr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, data) + data_offset; + if( 0 == pixels ) { + return 0; + } + + const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); const int bytes = 4 * width * height; // BGRA8888 DWORD dwWidth, dwHeight; @@ -2403,10 +2409,14 @@ Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, j hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD)0); - memcpy(lpBits, data_ptr, bytes); + memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes); ReleaseDC(NULL,hdc); + if ( JNI_FALSE == pixels_is_direct ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } + // Create an empty mask bitmap. HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL); diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index 19e733111..b62a9b234 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -678,13 +678,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage * Signature: (JJILjava/lang/Object;I)V */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0 - (JNIEnv *env, jclass clazz, jlong display, jobject data, jint data_offset, jint width, jint height, jint hotX, jint hotY) + (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY) { Cursor c; - if( 0 != data ) { + if( 0 != pixels ) { Display * dpy = (Display *) (intptr_t) display; - char * data_ptr = (char *) (*env)->GetDirectBufferAddress(env, data) + data_offset; + const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); XcursorImage ci; ci.version = 1; // XCURSOR_IMAGE_VERSION; ci.size = width; // nominal size (assume square ..) @@ -693,11 +695,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerI ci.xhot = hotX; ci.yhot = hotY; ci.delay = 0; - ci.pixels = (XcursorPixel *)(intptr_t)data_ptr; + ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset); c = XcursorImageLoadCursor (dpy, &ci); - DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", data_ptr, width, height, hotX, hotY, (void *)c); + if ( JNI_FALSE == pixels_is_direct ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } + DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c); } else { c = 0; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index da2778004..54b85c243 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -512,7 +512,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 jint visualID, jlong javaObjectAtom, jlong windowDeleteAtom, jint x, jint y, jint width, jint height, jboolean autoPosition, int flags, - jint iconDataSize, jobject iconData) + jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -632,10 +632,16 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 { XEvent event; int left=0, right=0, top=0, bottom=0; - - if( 0 < iconDataSize && NULL != iconData ) { - const unsigned char * iconDataPtr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, iconData); - NewtWindows_setIcon(dpy, window, (int)iconDataSize, iconDataPtr); + const unsigned char * pixelPtr = NULL; + + // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly! + DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct); + if( 0 < pixelDataSize && NULL != pixels ) { + pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); + DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr); + NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset); } XMapWindow(dpy, window); @@ -643,6 +649,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 XSync(dpy, False); + if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } + // send insets before visibility, allowing java code a proper sync point! NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom); (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index 8cc676291..780338492 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -29,6 +29,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; import java.io.IOException; +import java.net.URLConnection; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.Display; @@ -47,6 +48,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import javax.media.nativewindow.NativeWindowFactory; @@ -171,25 +173,55 @@ public class TestGearsES2NEWT extends UITestCase { } }); - final PointerIcon pointerIconOne; + final PointerIcon[] pointerIcons = { null, null, null }; { - PointerIcon _pointerIconOne = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); final Display disp = glWindow.getScreen().getDisplay(); disp.createNative(); - try { - _pointerIconOne = disp.createPointerIcon(res, 32, 0); - } catch (Exception e) { - e.printStackTrace(); + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 16, 16); + System.err.println("Create PointerIcon #01: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[0] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 32, 0); + System.err.println("Create PointerIcon #02: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[1] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "crosshair-lumina-trans-64x64.png" } ); + try { + final URLConnection urlConn = res.resolve(0); + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.println("Create PointerIcon #03: "+image); + _pointerIcon = disp.createPointerIcon(image, 32, 32); + System.err.println("Create PointerIcon #03: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[2] = _pointerIcon; } - pointerIconOne = _pointerIconOne; } if( setPointerIcon ) { - glWindow.setPointerIcon(pointerIconOne); + glWindow.setPointerIcon(pointerIcons[0]); System.err.println("Set PointerIcon: "+glWindow.getPointerIcon()); } glWindow.addKeyListener(new KeyAdapter() { + int pointerIconIdx = 0; + @Override public void keyPressed(final KeyEvent e) { if( e.isAutoRepeat() ) { @@ -246,7 +278,14 @@ public class TestGearsES2NEWT extends UITestCase { final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set pointer-icon pre]"); final PointerIcon currentPI = glWindow.getPointerIcon(); - glWindow.setPointerIcon( currentPI == pointerIconOne ? null : pointerIconOne); + final PointerIcon newPI; + if( pointerIconIdx >= pointerIcons.length ) { + newPI=null; + pointerIconIdx=0; + } else { + newPI=pointerIcons[pointerIconIdx++]; + } + glWindow.setPointerIcon( newPI ); System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); glWindow.setExclusiveContextThread(t); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java new file mode 100644 index 000000000..bb9bc42a8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java @@ -0,0 +1,54 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.util.texture; + +public class PNGTstFiles { + static public final String[] allBasenames = { + "test-ntscN_3-01-160x90", + "test-ntscN_4-01-160x90", + "test-ntscNG4-01-160x90", + "test-ntscI_3-01-160x90", + "test-ntscI_4-01-160x90", + "test-ntscIG3-01-160x90", + "test-ntscIG4-01-160x90", + "test-ntscP_3-01-160x90", + "test-ntscP_4-01-160x90", + "grayscale_texture", + "bug724-transparent-grey_orig", + "bug724-transparent-grey_gimpexp", + "crosshair-lumina-trans-32x32", + "crosshair-lumina-trans-64x64", + }; + static public final String[] greyBasenames = { + "grayscale_texture", + "bug724-transparent-grey_orig", + "bug724-transparent-grey_gimpexp", + "crosshair-lumina-trans-32x32", + "crosshair-lumina-trans-64x64", + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java deleted file mode 100644 index 3ace5ab6a..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.test.junit.jogl.util.texture; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URLConnection; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; - -import com.jogamp.common.util.IOUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.texture.spi.PNGImage; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestPNGImage00NEWT extends UITestCase { - @Test - public void testPNGReadWriteAndCompare() throws InterruptedException, IOException, MalformedURLException { - final File out1_f=new File(getSimpleTestName(".")+"-PNGImageTest1.png"); - final File out2_f=new File(getSimpleTestName(".")+"-PNGImageTest2.png"); - final File out2F_f=new File(getSimpleTestName(".")+"-PNGImageTest2Flipped.png"); - final File out2R_f=new File(getSimpleTestName(".")+"-PNGImageTest2Reversed.png"); - final File out2RF_f=new File(getSimpleTestName(".")+"-PNGImageTest2ReversedFlipped.png"); - final String url_s="jogl/util/data/av/test-ntsc01-57x32.png"; - URLConnection urlConn = IOUtil.getResource(url_s, this.getClass().getClassLoader()); - PNGImage image1 = PNGImage.read(urlConn.getInputStream()); - System.err.println("PNGImage - Orig: "+image1); - image1.write(out1_f, true); - { - Assert.assertEquals(image1.getData(), PNGImage.read(out1_f.toURI().toURL().openStream()).getData()); - } - - final PNGImage image2 = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), - image1.getDpi()[0], image1.getDpi()[1], - image1.getBytesPerPixel(), false /* reverseChannels */, image1.isGLOriented(), image1.getData()); - image2.write(out2_f, true); - { - Assert.assertEquals(image1.getData(), PNGImage.read(out2_f.toURI().toURL().openStream()).getData()); - } - - // flipped - final PNGImage image2F = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), - image1.getDpi()[0], image1.getDpi()[1], - image1.getBytesPerPixel(), false /* reverseChannels */, !image1.isGLOriented(), image1.getData()); - image2F.write(out2F_f, true); - - // reversed channels - final PNGImage image2R = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), - image1.getDpi()[0], image1.getDpi()[1], - image1.getBytesPerPixel(), true /* reverseChannels */, image1.isGLOriented(), image1.getData()); - image2R.write(out2R_f, true); - - // reversed channels and flipped - final PNGImage image2RF = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), - image1.getDpi()[0], image1.getDpi()[1], - image1.getBytesPerPixel(), true /* reverseChannels */, !image1.isGLOriented(), image1.getData()); - image2RF.write(out2RF_f, true); - } - - public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestPNGImage00NEWT.class.getName()); - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java deleted file mode 100644 index 29e041908..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java +++ /dev/null @@ -1,182 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.test.junit.jogl.util.texture; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URLConnection; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; - -import com.jogamp.common.util.IOUtil; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; -import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; -import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.QuitAdapter; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; -import com.jogamp.opengl.util.texture.TextureData; -import com.jogamp.opengl.util.texture.TextureIO; -import com.jogamp.opengl.util.texture.spi.PNGImage; - -/** - * Test reading and displaying a PNG image. - *

    - * Main function accepts arbitrary PNG file name for manual tests. - *

    - */ -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestPNGImage01NEWT extends UITestCase { - - static boolean showFPS = false; - static long duration = 200; // ms - - public void testImpl(final InputStream istream) throws InterruptedException, IOException { - final PNGImage image = PNGImage.read(istream); - Assert.assertNotNull(image); - final boolean hasAlpha = 4 == image.getBytesPerPixel(); - System.err.println("PNGImage: "+image); - - final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - if( hasAlpha ) { - caps.setAlphaBits(1); - } - - final int internalFormat; - if(glp.isGL2ES3()) { - internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; - } else { - internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; - } - final TextureData texData = new TextureData(glp, internalFormat, - image.getWidth(), - image.getHeight(), - 0, - new GLPixelAttributes(image.getGLFormat(), image.getGLType()), - false /* mipmap */, - false /* compressed */, - false /* must flip-vert */, - image.getData(), - null); - - // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG); - System.err.println("TextureData: "+texData); - - final GLWindow glad = GLWindow.create(caps); - glad.setTitle("TestPNGImage01NEWT"); - // Size OpenGL to Video Surface - glad.setSize(texData.getWidth(), texData.getHeight()); - - // load texture from file inside current GL context to match the way - // the bug submitter was doing it - final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ; - // gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } ); - - glad.addGLEventListener(gle); - glad.addGLEventListener(new GLEventListener() { - boolean shot = false; - - @Override public void init(GLAutoDrawable drawable) { - System.err.println("Chosen Caps: " + drawable.getChosenGLCapabilities()); - System.err.println("GL ctx: " + drawable.getGL().getContext()); - } - - @Override public void display(GLAutoDrawable drawable) { - // 1 snapshot - if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { - shot = true; - snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); - } - } - - @Override public void dispose(GLAutoDrawable drawable) { } - @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } - }); - - Animator animator = new Animator(glad); - animator.setUpdateFPSFrames(60, showFPS ? System.err : null); - QuitAdapter quitAdapter = new QuitAdapter(); - glad.addKeyListener(quitAdapter); - glad.addWindowListener(quitAdapter); - glad.setVisible(true); - animator.start(); - - while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration() + * Main function accepts arbitrary PNG file name for manual tests. + *

    + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPNGPixelRect01NEWT extends UITestCase { + static boolean showFPS = false; + static long duration = 200; // ms + + public void testImpl(final int num, final String basename, final InputStream istream, final PixelFormat destFmt) throws InterruptedException, IOException { + final GLProfile glp = GLProfile.getGL2ES2(); + final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); + Assert.assertNotNull(image); + final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp); + final boolean hasAlpha = 4 == glpa.bytesPerPixel; + System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa); + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCapabilities caps = new GLCapabilities(glp); + if( hasAlpha ) { + caps.setAlphaBits(1); + } + + final int internalFormat; + if(glp.isGL2ES3()) { + internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; + } else { + internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; + } + final TextureData texData = new TextureData(glp, internalFormat, + image.getSize().getWidth(), + image.getSize().getHeight(), + 0, + glpa, + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getPixels(), + null); + + // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle(this.getSimpleTestName(".")); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ; + // gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } ); + + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) { + System.err.println("Chosen Caps: " + drawable.getChosenGLCapabilities()); + System.err.println("GL ctx: " + drawable.getGL().getContext()); + } + + @Override public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(num, basename, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration() "+destFmt); + final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */); + System.err.println("PNGPixelRect - Conv1: "+imageConv1); + final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */); + System.err.println("PNGPixelRect - Conv2: "+imageConv2); + Assert.assertEquals(image1.getPixels(), imageConv2.getPixels()); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPixelFormatUtil01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png new file mode 100644 index 000000000..92279640b Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png differ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png new file mode 100644 index 000000000..9be285335 Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png differ diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index 69874df6b..70d01ae66 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -28,25 +28,27 @@ package com.jogamp.opengl.test.junit.newt.parenting; import java.awt.Frame; +import java.net.URLConnection; import javax.media.nativewindow.util.InsetsImmutable; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.Display; -import com.jogamp.newt.Window; import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.PNGPixelRect; public class NewtAWTReparentingKeyAdapter extends KeyAdapter { final Frame frame; final NewtCanvasAWT newtCanvasAWT; final GLWindow glWindow; final QuitAdapter quitAdapter; - PointerIcon pointerIconTest = null; + PointerIcon[] pointerIcons = null; + int pointerIconIdx = 0; public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow, QuitAdapter quitAdapter) { this.frame = frame; @@ -144,13 +146,46 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter { } } }.start(); } else if(e.getKeySymbol() == KeyEvent.VK_C ) { - if( null == pointerIconTest ) { - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } ); - final Display disp = glWindow.getScreen().getDisplay(); - try { - pointerIconTest = disp.createPointerIcon(res, 16, 0); - } catch (Exception err) { - err.printStackTrace(); + if( null == pointerIcons ) { + { + pointerIcons = new PointerIcon[3]; + final Display disp = glWindow.getScreen().getDisplay(); + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 16, 16); + System.err.println("Create PointerIcon #01: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[0] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 32, 0); + System.err.println("Create PointerIcon #02: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[1] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "crosshair-lumina-trans-64x64.png" } ); + try { + final URLConnection urlConn = res.resolve(0); + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.println("Create PointerIcon #03: "+image); + _pointerIcon = disp.createPointerIcon(image, 32, 32); + System.err.println("Create PointerIcon #03: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[2] = _pointerIcon; + } } } new Thread() { @@ -158,7 +193,14 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter { final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set pointer-icon pre]"); final PointerIcon currentPI = glWindow.getPointerIcon(); - glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest); + final PointerIcon newPI; + if( pointerIconIdx >= pointerIcons.length ) { + newPI=null; + pointerIconIdx=0; + } else { + newPI=pointerIcons[pointerIconIdx++]; + } + glWindow.setPointerIcon( newPI ); System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); glWindow.setExclusiveContextThread(t); } }.start(); -- cgit v1.2.3 From 6647b4a63866a554c738e0b7b61e6dc40a6fb511 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 11 Jan 2014 02:11:47 +0100 Subject: [Jogl|Nativewindow|Newt]Common: Align all *Common_GetJNIEnv()/_ReleaseJNIEnv() Methods and Usage / Check arguments .. Since we still don't use inter-module native code sharing, align the JNIEnv get/release methods and usage. Most beneficary here is OSX and the GLDebugMessageHandle, both managed the JVM handle on their own - removed now. Also ensuring that *Common_init(..) is called for all modules on all platforms. --- src/jogl/native/GLContext.c | 2 +- src/jogl/native/GLDebugMessageHandler.c | 95 ++++--------- src/jogl/native/JoglCommon.c | 97 ++++++------- src/jogl/native/JoglCommon.h | 55 ++++++-- src/jogl/native/libav/ffmpeg_impl_template.c | 4 +- .../macosx/MacOSXWindowSystemInterface-calayer.m | 1 + .../jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c | 5 +- src/nativewindow/native/NativewindowCommon.c | 110 ++++++++++----- src/nativewindow/native/NativewindowCommon.h | 61 ++++++++- src/nativewindow/native/macosx/OSXmisc.m | 34 ++--- src/nativewindow/native/win32/GDImisc.c | 2 +- src/nativewindow/native/x11/Xmisc.c | 126 +++++++---------- src/newt/native/MacWindow.m | 13 +- src/newt/native/NewtCommon.c | 96 +++++++++---- src/newt/native/NewtCommon.h | 26 ++-- src/newt/native/NewtMacWindow.h | 10 -- src/newt/native/NewtMacWindow.m | 152 ++++++--------------- 17 files changed, 431 insertions(+), 458 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/jogl/native/GLContext.c b/src/jogl/native/GLContext.c index f10d0e421..9be9f82af 100644 --- a/src/jogl/native/GLContext.c +++ b/src/jogl/native/GLContext.c @@ -19,7 +19,7 @@ Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jin assert(ptr_glGetString != NULL); _res = (* ptr_glGetString) ((unsigned int) name); if (NULL == _res) return NULL; - return (*env)->NewStringUTF(env, _res); + return (*env)->NewStringUTF(env, (const char *)_res); } /* diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c index 2e9d6033a..0aa7a01e7 100644 --- a/src/jogl/native/GLDebugMessageHandler.c +++ b/src/jogl/native/GLDebugMessageHandler.c @@ -49,8 +49,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_GLDebugMessageHandler_initIDs0 } typedef struct { - JavaVM *vm; - int version; jobject obj; int extType; } DebugHandlerType; @@ -60,39 +58,21 @@ typedef struct { static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam; - JavaVM *vm = handle->vm; - int version = handle->version; jobject obj = handle->obj; - JNIEnv *curEnv = NULL; - JNIEnv *newEnv = NULL; - int envRes ; - DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n", - message, handle->vm, handle->version, (void*)handle->obj, handle->extType); - - // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ; - DBG_PRINT("GLDebugMessageARBCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes); - if( JNI_EDETACHED == envRes ) { - // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) { - fprintf(stderr, "GLDebugMessageARBCallback: can't attach thread: %d\n", envRes); - return; - } - curEnv = newEnv; - DBG_PRINT("GLDebugMessageARBCallback: 02 - attached .. \n"); - } else if( JNI_OK != envRes ) { - // oops .. - fprintf(stderr, "GLDebugMessageARBCallback: can't GetEnv: %d\n", envRes); + JNIEnv *env = NULL; + int shallBeDetached ; + DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType); + + env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n"); return; } - (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageARB, + (*env)->CallVoidMethod(env, obj, glDebugMessageARB, (jint) source, (jint) type, (jint) id, (jint) severity, - (*curEnv)->NewStringUTF(curEnv, message)); - if( NULL != newEnv ) { - // detached attached thread - (*vm)->DetachCurrentThread(vm); - DBG_PRINT("GLDebugMessageARBCallback: 04 - detached .. \n"); - } + (*env)->NewStringUTF(env, message)); + // detaching thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT("GLDebugMessageARBCallback: 0X\n"); /** * On Java 32bit on 64bit Windows and w/ GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB disables, @@ -104,39 +84,21 @@ static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLe static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam; - JavaVM *vm = handle->vm; - int version = handle->version; jobject obj = handle->obj; - JNIEnv *curEnv = NULL; - JNIEnv *newEnv = NULL; - int envRes ; - DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n", - message, handle->vm, handle->version, (void*)handle->obj, handle->extType); - - // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ; - DBG_PRINT("GLDebugMessageAMDCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes); - if( JNI_EDETACHED == envRes ) { - // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) { - fprintf(stderr, "GLDebugMessageAMDCallback: can't attach thread: %d\n", envRes); - return; - } - curEnv = newEnv; - DBG_PRINT("GLDebugMessageAMDCallback: 02 - attached .. \n"); - } else if( JNI_OK != envRes ) { - // oops .. - fprintf(stderr, "GLDebugMessageAMDCallback: can't GetEnv: %d\n", envRes); + JNIEnv *env = NULL; + int shallBeDetached ; + DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType); + + env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n"); return; } - (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageAMD, + (*env)->CallVoidMethod(env, obj, glDebugMessageAMD, (jint) id, (jint) category, (jint) severity, - (*curEnv)->NewStringUTF(curEnv, message)); - if( NULL != newEnv ) { - // detached attached thread - (*vm)->DetachCurrentThread(vm); - DBG_PRINT("GLDebugMessageAMDCallback: 04 - detached .. \n"); - } + (*env)->NewStringUTF(env, message)); + // detached attached thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT("GLDebugMessageAMDCallback: 0X\n"); /** * On Java 32bit on 64bit Windows, @@ -153,18 +115,10 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0 (JNIEnv *env, jobject obj, jlong procAddress, jint extType) { - JavaVM *vm; DebugHandlerType * handle = malloc(sizeof(DebugHandlerType)); - if(0 != (*env)->GetJavaVM(env, &vm)) { - vm = NULL; - JoglCommon_throwNewRuntimeException(env, "GetJavaVM failed"); - } - handle->vm = vm; - handle->version = (*env)->GetVersion(env); handle->obj = (*env)->NewGlobalRef(env, obj); handle->extType = extType; - DBG_PRINT("GLDebugMessageHandler.register0: vm %p, version 0x%X, jobject %p, extType %d\n", - handle->vm, handle->version, (void*)handle->obj, handle->extType); + DBG_PRINT("GLDebugMessageHandler.register0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType); if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) { _local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB; @@ -191,8 +145,7 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0 { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) jhandle; - DBG_PRINT("GLDebugMessageHandler.unregister0: vm %p, version 0x%X, jobject %p, extType %d\n", - handle->vm, handle->version, (void*)handle->obj, handle->extType); + DBG_PRINT("GLDebugMessageHandler.unregister0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType); if(JNI_FALSE == (*env)->IsSameObject(env, obj, handle->obj)) { JoglCommon_throwNewRuntimeException(env, "wrong handle (obj doesn't match)"); diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c index 4170b13ec..e9984ada2 100644 --- a/src/jogl/native/JoglCommon.c +++ b/src/jogl/native/JoglCommon.c @@ -11,42 +11,38 @@ static JavaVM *_jvmHandle = NULL; static int _jvmVersion = 0; void JoglCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + JoglCommon_FatalError(env, "JOGL: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); if(NULL==c) { - JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException); + JoglCommon_FatalError(env, "JOGL: Can't find %s", ClazzNameRuntimeException); } runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==runtimeExceptionClz) { - JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException); + JoglCommon_FatalError(env, "JOGL: Can't use %s", ClazzNameRuntimeException); } } - if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { - JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle"); - } else { - _jvmVersion = (*env)->GetVersion(env); - } } void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - int shallBeDetached = 0; - - if(NULL == env) { - env = JoglCommon_GetJNIEnv (&shallBeDetached); - } - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - fprintf(stderr, "%s\n", buffer); - if(NULL != env) { - (*env)->FatalError(env, buffer); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } } } @@ -54,48 +50,42 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - int shallBeDetached = 0; - if(NULL == env) { - env = JoglCommon_GetJNIEnv (&shallBeDetached); + if(NULL==_jvmHandle) { + JoglCommon_FatalError(env, "JOGL: NULL JVM handle, call JoglCommon_init 1st\n"); + return; } - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - if(NULL != env) { - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); + } } } -JavaVM *JoglCommon_GetJVMHandle() { - return _jvmHandle; -} - -int JoglCommon_GetJVMVersion() { - return _jvmVersion; -} - jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) -{ +JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; - if(NULL == _jvmHandle) { - fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st"); + if(NULL==_jvmHandle) { + fprintf(stderr, "JOGL GetJNIEnv: NULL JVM handle, call JoglCommon_init 1st\n"); return NULL; } @@ -103,18 +93,23 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL) ) ) { - fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); + if( asDaemon ) { + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); + } else { + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); + } + if( JNI_OK != envRes ) { + fprintf(stderr, "JOGL GetJNIEnv: Can't attach thread: %d\n", envRes); return NULL; } curEnv = newEnv; } else if( JNI_OK != envRes ) { // oops .. - fprintf(stderr, "can't GetEnv: %d\n", envRes); + fprintf(stderr, "JOGL GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "JOGL GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; @@ -123,10 +118,8 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) void JoglCommon_ReleaseJNIEnv (int shallBeDetached) { if(NULL == _jvmHandle) { - fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st"); - } - - if(shallBeDetached) { + fprintf(stderr, "JOGL ReleaseJNIEnv: No JavaVM handle registered, call JoglCommon_init(..) 1st"); + } else if(shallBeDetached) { (*_jvmHandle)->DetachCurrentThread(_jvmHandle); } } diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h index 023b4be03..2aeaf7d1d 100644 --- a/src/jogl/native/JoglCommon.h +++ b/src/jogl/native/JoglCommon.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef JOGL_COMMON_H #define JOGL_COMMON_H 1 @@ -7,29 +34,25 @@ void JoglCommon_init(JNIEnv *env); -/** Set by JoglCommon_init */ -JavaVM *JoglCommon_GetJVMHandle(); - -/** Set by JoglCommon_init */ -int JoglCommon_GetJVMVersion(); - jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str); -/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */ void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...); - -/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); /** * - * 1) Store jvmHandle and jvmVersion is done by 'JoglCommon_init(JNIEnv*)' - * and internally used by 'JoglCommon_GetJNIEnv(..)' and 'JoglCommon_ReleaseJNIEnv(..)'. + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' + + JoglCommon_init(env); + * * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv * + + int asDaemon = 0; int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(&shallBeDetached); + JNIEnv* env = JoglCommon_GetJNIEnv(asDaemon, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -41,11 +64,13 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); .. your JNIEnv code here .. * - * 4) Detach thread from JVM, if required + * 4) Detach thread from JVM if required, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) * - JoglCommon_ReleaseJNIEnv (shallBeDetached); + JoglCommon_ReleaseJNIEnv(shallBeDetached); */ -JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached); +JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + void JoglCommon_ReleaseJNIEnv (int shallBeDetached); #endif diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index 44acfe46a..e86b2a542 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -1499,7 +1499,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) int64_t pts1 = (int64_t) (pos1 * (int64_t) time_base.den) / (1000 * (int64_t) time_base.num); if(pAV->verbose) { - fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %d, pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1); + fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %"PRId64", pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1); } int flags = 0; if(pos1 < pos0) { @@ -1508,7 +1508,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) int res = -2; if(HAS_FUNC(sp_av_seek_frame)) { if(pAV->verbose) { - fprintf(stderr, "SEEK.0: pre : s %d / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1); + fprintf(stderr, "SEEK.0: pre : s %"PRId64" / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1); } sp_av_seek_frame(pAV->pFormatCtx, streamID, pts1, flags); } else if(HAS_FUNC(sp_avformat_seek_file)) { diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m index 75917d2dc..7ce8c58cf 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -578,6 +578,7 @@ static const GLfloat gl_verts[] = { quirks, dedicatedFramePosSet, dedicatedFrameSizeSet, dedicatedLayoutSet, self, texWidth, texHeight, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, dFrame.origin.x, dFrame.origin.y, dFrame.size.width, dFrame.size.height); + (void)lRect; // silence if( dedicatedFrameSet ) { [super setFrame: dedicatedFrame]; diff --git a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c index ec68a24aa..3166306ba 100644 --- a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c +++ b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c @@ -67,7 +67,7 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV) return; } int shallBeDetached = 0; - JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached); + JNIEnv * env = JoglCommon_GetJNIEnv (1 /* daemon */, &shallBeDetached); if(NULL!=env) { (*env)->CallVoidMethod(env, (jobject)pAV->jni_instance, jni_mid_updateAttributes, pAV->width, pAV->height, @@ -75,7 +75,8 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV) pAV->framerate, (uint32_t)(pAV->length*pAV->framerate), pAV->length, (*env)->NewStringUTF(env, pAV->videoCodec), (*env)->NewStringUTF(env, pAV->audioCodec) ); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + // detaching thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); } } diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index ec7ee7728..e65f87272 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -8,41 +8,24 @@ static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; -void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - fprintf(stderr, "%s\n", buffer); - (*env)->FatalError(env, buffer); -} - -void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); -} +static JavaVM *_jvmHandle = NULL; +static int _jvmVersion = 0; int NativewindowCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + NativewindowCommon_FatalError(env, "Nativewindow: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); if(NULL==c) { - NativewindowCommon_FatalError(env, "Nativewindow: can't find %s", ClazzNameRuntimeException); + NativewindowCommon_FatalError(env, "Nativewindow: Can't find %s", ClazzNameRuntimeException); } runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==runtimeExceptionClz) { - NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException); + NativewindowCommon_FatalError(env, "Nativewindow: Can't use %s", ClazzNameRuntimeException); } #ifdef STDERR_TO_FILE FILE * old_stderr = stderr; @@ -54,6 +37,44 @@ int NativewindowCommon_init(JNIEnv *env) { return 0; } +void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } + } +} + +void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + if(NULL==_jvmHandle) { + NativewindowCommon_FatalError(env, "Nativewindow: NULL JVM handle, call NativewindowCommon_init 1st\n"); + return; + } + + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); + } + } +} + const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) { if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) { jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID); @@ -75,45 +96,60 @@ const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass cla jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { +JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; + if(NULL==_jvmHandle) { + fprintf(stderr, "Nativewindow GetJNIEnv: NULL JVM handle, call NativewindowCommon_init 1st\n"); + return NULL; + } + // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ; + envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM if( asDaemon ) { - envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); } else { - envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); } if( JNI_OK != envRes ) { - fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); + fprintf(stderr, "Nativewindow GetJNIEnv: Can't attach thread: %d\n", envRes); return NULL; } curEnv = newEnv; } else if( JNI_OK != envRes ) { // oops .. - fprintf(stderr, "can't GetEnv: %d\n", envRes); + fprintf(stderr, "Nativewindow GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "Nativewindow GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; return curEnv; } +void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached) { + if(NULL == _jvmHandle) { + fprintf(stderr, "Nativewindow ReleaseJNIEnv: No JavaVM handle registered, call NativewindowCommon_init(..) 1st"); + } else if(shallBeDetached) { + (*_jvmHandle)->DetachCurrentThread(_jvmHandle); + } +} + int64_t NativewindowCommon_CurrentTimeMillis() { struct timeval tv; gettimeofday(&tv,NULL); diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h index a23fad9fd..f19552e33 100644 --- a/src/nativewindow/native/NativewindowCommon.h +++ b/src/nativewindow/native/NativewindowCommon.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef NATIVEWINDOW_COMMON_H #define NATIVEWINDOW_COMMON_H 1 @@ -14,7 +41,39 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...); void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); +/** + * + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' + + NativewindowCommon_init(env); + + * + * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv + * + + int asDaemon = 0; + int shallBeDetached = 0; + JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached); + if(NULL==env) { + DBG_PRINT("drawRect: null JNIEnv\n"); + return; + } + + * + * 3) Use JNIEnv .. + * + .. your JNIEnv code here .. + + * + * 4) Detach thread from JVM if required, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) + * + NewtCommon_ReleaseJNIEnv(shallBeDetached); + */ +JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + +void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached); int64_t NativewindowCommon_CurrentTimeMillis(); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 6a7952eaf..4887cc3cf 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -75,11 +75,9 @@ static const char * const ClazzNameInsetsCstrSignature = "(IIII)V"; static jclass insetsClz = NULL; static jmethodID insetsCstr = NULL; -static int _initialized=0; - JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { - if(0==_initialized) { + if( NativewindowCommon_init(env) ) { jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { @@ -119,7 +117,6 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { if(NULL==runnableRunID) { NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable); } - _initialized=1; } return JNI_TRUE; } @@ -775,12 +772,10 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns @interface MainRunnable : NSObject { - JavaVM *jvmHandle; - int jvmVersion; jobject runnableObj; } -- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers; +- (id) initWithRunnable: (jobject)runnable; - (void) jRun; #ifdef DBG_LIFECYCLE @@ -794,10 +789,8 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns @implementation MainRunnable -- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers +- (id) initWithRunnable: (jobject)runnable { - jvmHandle = jvm; - jvmVersion = jvmVers; runnableObj = runnable; return [super init]; } @@ -805,7 +798,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns - (void) jRun { int shallBeDetached = 0; - JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env)); if(NULL!=env) { DBG_PRINT2("MainRunnable.1.0\n"); @@ -813,11 +806,9 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns DBG_PRINT2("MainRunnable.1.1\n"); (*env)->DeleteGlobalRef(env, runnableObj); - if (shallBeDetached) { - DBG_PRINT2("MainRunnable.1.3\n"); - // Keep attached on main thread ! - // (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + DBG_PRINT2("MainRunnable.1.3\n"); + // detaching thread not required - daemon + // NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } DBG_PRINT2("MainRunnable.X\n"); } @@ -861,17 +852,8 @@ static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayI if ( forkOnMain ) { jobject runnableObj = (*env)->NewGlobalRef(env, runnable); - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } - DBG_PRINT2( "RunOnThread.1.0\n"); - MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion]; + MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj]; if( onMain ) { [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO]; diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c index e28f68e7d..bec1d4922 100644 --- a/src/nativewindow/native/win32/GDImisc.c +++ b/src/nativewindow/native/win32/GDImisc.c @@ -487,7 +487,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindo JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0 (JNIEnv *env, jclass gdiClazz) { - if(NativewindowCommon_init(env)) { + if( NativewindowCommon_init(env) ) { jclass c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't find %s", ClazzNamePoint); diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 5e6909f6e..247dc1311 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -113,68 +113,56 @@ static jmethodID pointCstr = NULL; static void _initClazzAccess(JNIEnv *env) { jclass c; - if(!NativewindowCommon_init(env)) return; - - getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;"); - if(NULL==getCurrentThreadNameID) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName"); - } - dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V"); - if(NULL==dumpStackID) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack"); - } - - c = (*env)->FindClass(env, ClazzNameBuffers); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers); - } - clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==clazzBuffers) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers); - } - c = (*env)->FindClass(env, ClazzNameByteBuffer); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer); - } - clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer); - } - - cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers, - ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); - if(NULL==cstrBuffers) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s", - ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); - } + if( NativewindowCommon_init(env) ) { + getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;"); + if(NULL==getCurrentThreadNameID) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName"); + } + dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V"); + if(NULL==dumpStackID) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack"); + } - c = (*env)->FindClass(env, ClazzNamePoint); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint); - } - pointClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==pointClz) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint); - } - pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); - if(NULL==pointCstr) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s", - ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); - } -} + c = (*env)->FindClass(env, ClazzNameBuffers); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers); + } + clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==clazzBuffers) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers); + } + c = (*env)->FindClass(env, ClazzNameByteBuffer); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer); + } + clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer); + } -static JavaVM *jvmHandle = NULL; -static int jvmVersion = 0; + cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers, + ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); + if(NULL==cstrBuffers) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s", + ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); + } -static void setupJVMVars(JNIEnv * env) { - if( NULL != env && NULL == jvmHandle ) { - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; + c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint); + } + pointClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==pointClz) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint); + } + pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); + if(NULL==pointCstr) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s", + ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } - jvmVersion = (*env)->GetVersion(env); } } @@ -201,8 +189,8 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e) (int)e->request_code, (int)e->minor_code, reqCodeStr); fflush(stderr); - if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); + if( errorHandlerDebug || errorHandlerThrowException ) { + jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached); if(NULL == jniEnv) { fprintf(stderr, "Nativewindow X11 Error: null JNIEnv"); fflush(stderr); @@ -219,9 +207,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e) e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial, (int)e->request_code, (int)e->minor_code, reqCodeStr); } - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } } @@ -233,7 +219,6 @@ static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, if(onoff) { if(force || NULL==origErrorHandler) { XErrorHandler prevErrorHandler; - setupJVMVars(env); prevErrorHandler = XSetErrorHandler(x11ErrorHandler); if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler origErrorHandler = prevErrorHandler; @@ -265,14 +250,10 @@ static int x11IOErrorHandler(Display *dpy) fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr); fflush(stderr); - if( NULL != jvmHandle ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); - if (NULL != jniEnv) { - NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr); - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } - } + jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached); + if (NULL != jniEnv) { + NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr); + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } if(NULL!=origIOErrorHandler) { origIOErrorHandler(dpy); @@ -283,7 +264,6 @@ static int x11IOErrorHandler(Display *dpy) static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) { if(onoff) { if(NULL==origIOErrorHandler) { - setupJVMVars(env); origIOErrorHandler = XSetIOErrorHandler(x11IOErrorHandler); } } else { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index c6fd805a5..130b2e3e3 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -113,18 +113,6 @@ static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtVi DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject); jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject); [view setJavaWindowObject: globJavaWindowObject]; - { - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } - [view setJVMHandle: jvmHandle]; - [view setJVMVersion: jvmVersion]; - } } DBG_PRINT( "setJavaWindowObject.X: View %p\n", view); } @@ -979,6 +967,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]]; NSWindow *pWin = [mWin parentWindow]; DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); + (void)isNSWin; // silence if( !isNewtWin ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c index c294b6e0b..231d6182f 100644 --- a/src/newt/native/NewtCommon.c +++ b/src/newt/native/NewtCommon.c @@ -5,17 +5,43 @@ static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; +static JavaVM *_jvmHandle = NULL; +static int _jvmVersion = 0; + +void NewtCommon_init(JNIEnv *env) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } + jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); + if(NULL==c) { + NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException); + } + runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==runtimeExceptionClz) { + NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException); + } + } +} + void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - fprintf(stderr, "%s\n", buffer); - (*env)->FatalError(env, buffer); + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } + } } void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) @@ -23,23 +49,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) char buffer[512]; va_list ap; - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if(NULL==_jvmHandle) { + NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n"); + return; + } - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); -} + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); -void NewtCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { - jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); - if(NULL==c) { - NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException); - } - runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==runtimeExceptionClz) { - NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException); + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); } } } @@ -65,42 +86,57 @@ const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmet jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { +JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; + if(NULL==_jvmHandle) { + fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n"); + return NULL; + } + // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ; + envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM if( asDaemon ) { - envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); } else { - envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); } if( JNI_OK != envRes ) { - fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); + fprintf(stderr, "NEWT GetJNIEnv: Can't attach thread: %d\n", envRes); return NULL; } curEnv = newEnv; } else if( JNI_OK != envRes ) { // oops .. - fprintf(stderr, "can't GetEnv: %d\n", envRes); + fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; return curEnv; } +void NewtCommon_ReleaseJNIEnv (int shallBeDetached) { + if(NULL == _jvmHandle) { + fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st"); + } else if(shallBeDetached) { + (*_jvmHandle)->DetachCurrentThread(_jvmHandle); + } +} + diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 9cc9e93a6..43db72b5b 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -42,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); /** * - * 1) Store jvmHandle and jvmVersion + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } + NewtCommon_init(env); * * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv * + int asDaemon = 0; int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -70,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); .. your JNIEnv code here .. * - * 4) Detach thread from JVM, if required + * 4) Detach thread from JVM if required, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) * - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); */ -JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); +JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + +void NewtCommon_ReleaseJNIEnv (int shallBeDetached); #endif diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index daf75bec7..8f6362ac2 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -53,10 +53,6 @@ { jobject javaWindowObject; - // This is set while messages are being dispatched and cleared afterward - JavaVM *jvmHandle; - int jvmVersion; - volatile BOOL destroyNotifySent; volatile int softLockCount; pthread_mutex_t softLockSync; @@ -80,12 +76,6 @@ #endif - (void) dealloc; -/* Set during event dispatching cycle */ -- (void) setJVMHandle: (JavaVM*) vm; -- (JavaVM*) getJVMHandle; -- (void) setJVMVersion: (int) ver; -- (int) getJVMVersion; - /* Register or deregister (NULL) the java Window object, ie, if NULL, no events are send */ - (void) setJavaWindowObject: (jobject) javaWindowObj; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 5ccd9c658..b4133ac7e 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -193,8 +193,6 @@ static jmethodID windowRepaintID = NULL; id res = [super initWithFrame:frameRect]; javaWindowObject = NULL; - jvmHandle = NULL; - jvmVersion = 0; destroyNotifySent = NO; softLockCount = 0; @@ -244,25 +242,6 @@ static jmethodID windowRepaintID = NULL; [super dealloc]; } -- (void) setJVMHandle: (JavaVM*) vm -{ - jvmHandle = vm; -} -- (JavaVM*) getJVMHandle -{ - return jvmHandle; -} - -- (void) setJVMVersion: (int) ver -{ - jvmVersion = ver; -} - -- (int) getJVMVersion -{ - return jvmVersion; -} - - (void) setJavaWindowObject: (jobject) javaWindowObj { javaWindowObject = javaWindowObj; @@ -342,7 +321,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -354,9 +333,8 @@ static jmethodID windowRepaintID = NULL; dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void) viewDidHide @@ -366,7 +344,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidHide: null JNIEnv\n"); return; @@ -374,9 +352,8 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); [super viewDidHide]; } @@ -388,7 +365,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidUnhide: null JNIEnv\n"); return; @@ -396,9 +373,8 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); [super viewDidUnhide]; } @@ -645,14 +621,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("sendMouseEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("sendMouseEvent: null JNIEnv\n"); return; } jint javaMods[] = { 0 } ; @@ -700,9 +671,8 @@ static jmethodID windowRepaintID = NULL; (jint) location.x, (jint) location.y, javaButtonNum, scrollDeltaY); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p @@ -754,14 +724,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("sendKeyEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("sendKeyEvent: null JNIEnv\n"); return; } @@ -792,9 +757,8 @@ static jmethodID windowRepaintID = NULL; evType, javaMods, keyCode, keyChar, keyChar); } - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } @end @@ -1038,23 +1002,16 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("focusChanged: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("focusChanged: null JNIEnv\n"); return; } (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void) keyDown: (NSEvent*) theEvent @@ -1147,37 +1104,31 @@ static jmethodID windowRepaintID = NULL; - (void)windowDidResize: (NSNotification*) notification { - JNIEnv* env = NULL; jobject javaWindowObject = NULL; int shallBeDetached = 0; - JavaVM *jvmHandle = NULL; + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("windowDidResize: null JNIEnv\n"); + return; + } NewtView* newtView = (NewtView *) [self contentView]; if( [newtView isKindOfClass:[NewtView class]] ) { javaWindowObject = [newtView getJavaWindowObject]; - if (javaWindowObject != NULL) { - jvmHandle = [newtView getJVMHandle]; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } - } } + if( NULL != javaWindowObject ) { + // update insets on every window resize for lack of better hook place + [self updateInsets: env jwin:javaWindowObject]; - // update insets on every window resize for lack of better hook place - [self updateInsets: env jwin:javaWindowObject]; - - if( NULL != env && NULL != javaWindowObject ) { NSRect frameRect = [self frame]; NSRect contentRect = [self contentRectForFrameRect: frameRect]; (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE, (jint) contentRect.size.width, (jint) contentRect.size.height, JNI_FALSE); - - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ } + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void)windowDidMove: (NSNotification*) notification @@ -1192,15 +1143,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("windowDidMove: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("windowDidMove: null JNIEnv\n"); return; } @@ -1208,9 +1153,8 @@ static jmethodID windowRepaintID = NULL; p0 = [self getLocationOnScreen: p0]; (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (BOOL)windowShouldClose: (id) sender @@ -1226,13 +1170,12 @@ static jmethodID windowRepaintID = NULL; - (BOOL) windowClosingImpl: (BOOL) force { jboolean closed = JNI_FALSE; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* newtView = (NewtView *) [self contentView]; if( ! [newtView isKindOfClass:[NewtView class]] ) { return NO; } - + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [newtView cursorHide: NO enter: -1]; if( false == [newtView getDestroyNotifySent] ) { @@ -1240,26 +1183,16 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); + [pool release]; return NO; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env = NULL; -NS_DURING - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } -NS_HANDLER - jvmHandle = NULL; - env = NULL; - [newtView setJVMHandle: NULL]; - DBG_PRINT("windowWillClose: JVMHandler Exception\n"); -NS_ENDHANDLER - DBG_PRINT("windowWillClose: JVM %p JNIEnv %p\n", jvmHandle, env); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { + DBG_PRINT("windowWillClose: null JNIEnv\n"); + [pool release]; return NO; } - [newtView setDestroyNotifySent: true]; // earmark assumption of being closed closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE); if(!force && !closed) { @@ -1267,9 +1200,8 @@ NS_ENDHANDLER [newtView setDestroyNotifySent: false]; } - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); -- cgit v1.2.3 From c3c204a2e374c1dc4c1fb51f15444e5b92850839 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 10 Feb 2014 18:46:28 +0100 Subject: Bug 970: NEWT OSX ChildWindow setVisible(..) does not hide child window appropriately Instead of using [mWin orderBack: mWin] for child windows, utilize [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]] --- src/newt/native/MacWindow.m | 20 +++--- .../junit/newt/parenting/TestParenting01NEWT.java | 83 ++++++++++++++++++++-- 2 files changed, 91 insertions(+), 12 deletions(-) (limited to 'src/newt/native/MacWindow.m') diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 130b2e3e3..25ea47c47 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -1133,13 +1133,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) window); + NSWindow* mWin = (NSWindow*) ((intptr_t) window); + NSWindow* pWin = [mWin parentWindow]; - DBG_PRINT( "orderFront0 - window: %p (START)\n", win); + DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); - [win orderFrontRegardless]; + if( NULL == pWin ) { + [mWin orderFrontRegardless]; + } else { + [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]]; + } - DBG_PRINT( "orderFront0 - window: %p (END)\n", win); + DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin); [pool release]; } @@ -1155,14 +1160,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) window); NSWindow* pWin = [mWin parentWindow]; - BOOL pWinVisible = NULL != pWin ? [pWin isVisible] : 0; - DBG_PRINT( "orderOut0 - window: (parent %p visible %d) %p visible %d (START)\n", pWin, pWinVisible, mWin, [mWin isVisible]); + DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); - if( NULL == pWin || !pWinVisible ) { + if( NULL == pWin ) { [mWin orderOut: mWin]; } else { - [mWin orderBack: mWin]; + [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java index 7beceb291..714c397f3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java @@ -374,10 +374,28 @@ public class TestParenting01NEWT extends UITestCase { int state = 0; Window.ReparentOperation reparentAction; - while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) { + while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) { Thread.sleep(durationPerTest); switch(state) { case 0: + // top-level glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 1: + // top-level glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 2: // glWindow2 -- child --> glWindow1: compatible Assert.assertEquals(true, glWindow2.isVisible()); System.err.println("Frames(1) "+glWindow2.getTotalFPSFrames()); @@ -403,7 +421,25 @@ public class TestParenting01NEWT extends UITestCase { break; - case 1: + case 3: + // child glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 4: + // child glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 5: // glWindow2 --> top Assert.assertEquals(true, glWindow2.isVisible()); @@ -566,10 +602,29 @@ public class TestParenting01NEWT extends UITestCase { int state = 0; Window.ReparentOperation reparentAction; - while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) { + while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) { Thread.sleep(durationPerTest); switch(state) { case 0: + // child glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 1: + // child glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 2: + // glWindow2 --> top Assert.assertEquals(true, glWindow2.isVisible()); reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); @@ -584,7 +639,27 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertSame(display1,glWindow2.getScreen().getDisplay()); Assert.assertEquals(1,Display.getActiveDisplayNumber()); break; - case 1: + + case 3: + // top-level glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 4: + // top-level glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 5: + // glWindow2 -- child --> glWindow1: compatible Assert.assertEquals(true, glWindow2.isVisible()); reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); -- cgit v1.2.3