diff options
author | Sven Gothel <[email protected]> | 2010-11-03 07:37:31 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-11-03 07:37:31 +0100 |
commit | a0e9d6c8382b7275db6fae664be44db6b59671d5 (patch) | |
tree | 135b6c0924e992f19666bdf564bc64b74a4dd8f9 /src | |
parent | 701cc44d7b2c9f0b7fd977ca29951c2fb779ce2f (diff) |
NEWT Window Lifecycle / ScreenMode:
Lifecycle.reparentActionPre()/reparentActionPost() -> pauseRenderingAction()/resumeRenderingAction()
for a more generic use, ie reparenting and screen mode change.
ScreenMode change: No more visibility/fullscreen changes, no more locking,
just pause/resume animation.
X11 ScreenMode set: move from thread/wait to simple polling over time (timeout)
Diffstat (limited to 'src')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/WindowImpl.java | 71 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java | 64 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/opengl/GLWindow.java | 5 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 84 |
4 files changed, 117 insertions, 107 deletions
diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java index 7d80712e6..dfa768147 100644 --- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java @@ -163,11 +163,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod */ void destroyActionInLock(boolean unrecoverable); - /** Only informal, when starting reparenting */ - void reparentActionPre(); + /** + * Invoked for expensive modifications, ie while reparenting and ScreenMode change.<br> + * No lock is hold when invoked.<br> + * + * @see #resumeRenderingAction() + */ + void pauseRenderingAction(); - /** Only informal, when finishing reparenting */ - void reparentActionPost(int reparentActionType); + /** + * Invoked for expensive modifications, ie while reparenting and ScreenMode change. + * No lock is hold when invoked.<br> + * + * @see #pauseRenderingAction() + */ + void resumeRenderingAction(); } private LifecycleHook lifecycleHook = null; @@ -475,13 +485,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod class VisibleAction implements Runnable { boolean visible; - long timeOut; boolean nativeWindowCreated; boolean madeVisible; - public VisibleAction (boolean visible, long timeOut) { + public VisibleAction (boolean visible) { this.visible = visible; - this.timeOut = timeOut; this.nativeWindowCreated = false; this.madeVisible = false; } @@ -510,13 +518,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod if(0==windowHandle && visible) { if( 0<width*height ) { nativeWindowCreated = createNative(); - WindowImpl.this.waitForVisible(visible, true, timeOut); + WindowImpl.this.waitForVisible(visible, true); madeVisible = visible; } } else if(WindowImpl.this.visible != visible) { if(0 != windowHandle) { setVisibleImpl(visible, x, y, width, height); - WindowImpl.this.waitForVisible(visible, true, timeOut); + WindowImpl.this.waitForVisible(visible, true); madeVisible = visible; } } @@ -545,17 +553,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod } public void setVisible(boolean visible) { - setVisible(visible, TIMEOUT_NATIVEWINDOW); - - } - - protected final void setVisible(boolean visible, long timeOut) { if(isValid()) { if( 0==windowHandle && visible && 0>=width*height ) { // fast-path: not realized yet, make visible, but zero size return; } - VisibleAction visibleAction = new VisibleAction(visible, timeOut); + VisibleAction visibleAction = new VisibleAction(visible); runOnEDTIfAvail(true, visibleAction); if( visibleAction.getChanged() ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener @@ -1034,20 +1037,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod int reparentActionStrategy = ReparentAction.ACTION_INVALID; if(isValid()) { if(null!=lifecycleHook) { - lifecycleHook.reparentActionPre(); + // pause animation + lifecycleHook.pauseRenderingAction(); } try { ReparentActionImpl reparentAction = new ReparentActionImpl(newParent, forceDestroyCreate); runOnEDTIfAvail(true, reparentAction); reparentActionStrategy = reparentAction.getStrategy(); - if( isVisible() ) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener - } } finally { if(null!=lifecycleHook) { - lifecycleHook.reparentActionPost(reparentActionStrategy); + // resume animation + lifecycleHook.resumeRenderingAction(); } } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } return reparentActionStrategy; } @@ -1379,7 +1382,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod display.dispatchMessagesNative(); // status up2date boolean wasVisible = isVisible(); setVisibleImpl(false, x, y, width, height); - WindowImpl.this.waitForVisible(false, true, Screen.SCREEN_MODE_CHANGE_TIMEOUT); + WindowImpl.this.waitForVisible(false, true); display.dispatchMessagesNative(); // status up2date // write back mirrored values, to be able to detect satisfaction @@ -1429,29 +1432,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod return this.fullscreen; } - boolean screenModeChangeVisible; - boolean screenModeChangeFullscreen; - public void screenModeChangeNotify(ScreenMode sm) { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { System.err.println("Window.screenModeChangeNotify: "+sm); } - screenModeChangeFullscreen = isFullscreen(); - if(screenModeChangeFullscreen) { - setFullscreen(false); - } - screenModeChangeVisible = isVisible(); - if(screenModeChangeVisible) { - setVisible(false); + + if(null!=lifecycleHook) { + // pause animation + lifecycleHook.pauseRenderingAction(); } - windowLock.lock(); } public void screenModeChanged(ScreenMode sm, boolean success) { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { System.err.println("Window.screenModeChanged: "+sm+", success: "+success); } - windowLock.unlock(); if(success) { DimensionReadOnly screenSize = sm.getMonitorMode().getSurfaceSize().getResolution(); @@ -1460,11 +1455,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod setSize(screenSize.getWidth(), screenSize.getHeight()); } } - if(screenModeChangeFullscreen) { - setFullscreen(true); - } - if(screenModeChangeVisible) { - setVisible(true, Screen.SCREEN_MODE_CHANGE_TIMEOUT); + + if(null!=lifecycleHook) { + // resume animation + lifecycleHook.resumeRenderingAction(); + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java index 3f49b5e79..5e89a9972 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java @@ -211,51 +211,34 @@ public class X11Screen extends ScreenImpl { if(0>resIdx || resIdx>=resNumber) { throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode); } - String tname = Thread.currentThread()+"-X11Screen.setCurrentScreenModeImpl()"; - SetScreenModeAction setScreenModeAction = new SetScreenModeAction(screenMode, resIdx); - Thread randrTask = new Thread(setScreenModeAction, tname); - randrTask.start(); - int to = SCREEN_MODE_CHANGE_TIMEOUT / 100 ; - while(to>0 && randrTask.isAlive()) { - try { - Thread.sleep(100); - } catch (InterruptedException ex) { } - to--; - } - if(0==to && DEBUG) { - System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ - randrTask+", alive "+randrTask.isAlive()); - } - return setScreenModeAction.getResult(); - } - - class SetScreenModeAction implements Runnable { - boolean res; - ScreenMode screenMode; - int resIdx; - public SetScreenModeAction(ScreenMode screenMode, int resIdx) { - this.screenMode = screenMode; - this.resIdx = resIdx; - this.res = false; + long dpy = X11Util.createDisplay(display.getName()); + if( 0 == dpy ) { + throw new RuntimeException("Error creating display: "+display.getName()); } - public boolean getResult() { - return res; + boolean done = false; + long t0 = System.currentTimeMillis(); + try { + int f = screenMode.getMonitorMode().getRefreshRate(); + int r = screenMode.getRotation(); + if( setCurrentScreenModeStart0(dpy, screen_idx, resIdx, f, r) ) { + while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) { + done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r); + if(!done) { + Thread.yield(); + } + } + } + } finally { + X11Util.closeDisplay(dpy); } - public void run() { - long dpy = X11Util.createDisplay(display.getName()); - if( 0 == dpy ) { - throw new RuntimeException("Error creating display: "+display.getName()); - } - try { - res = setCurrentScreenMode0(dpy, screen_idx, resIdx, - screenMode.getMonitorMode().getRefreshRate(), screenMode.getRotation()); - } finally { - X11Util.closeDisplay(dpy); - } + if(!done) { + System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ + (System.currentTimeMillis()-t0)+"ms"); } + return done; } //---------------------------------------------------------------------- @@ -282,5 +265,6 @@ public class X11Screen extends ScreenImpl { private static native int getCurrentScreenRotation0(long display, int screen_index); /** needs own Display connection for XRANDR event handling */ - private static native boolean setCurrentScreenMode0(long display, int screen_index, int mode_index, int freq, int rot); + private static native boolean setCurrentScreenModeStart0(long display, int screen_index, 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/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 7836bec68..36302c55a 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -367,7 +367,7 @@ public class GLWindow implements GLAutoDrawable, Window { boolean animatorPaused = false; - public synchronized void reparentActionPre() { + public synchronized void pauseRenderingAction() { GLAnimatorControl ctrl = GLWindow.this.getAnimator(); if ( null!=ctrl && ctrl.isAnimating() && ctrl.getThread() != Thread.currentThread() ) { animatorPaused = true; @@ -375,7 +375,7 @@ public class GLWindow implements GLAutoDrawable, Window { } } - public synchronized void reparentActionPost(int reparentActionType) { + public synchronized void resumeRenderingAction() { resetCounter(); GLAnimatorControl ctrl = GLWindow.this.getAnimator(); if ( null!=ctrl && animatorPaused ) { @@ -384,6 +384,7 @@ public class GLWindow implements GLAutoDrawable, Window { } } } + //---------------------------------------------------------------------- // OpenGL-related methods and state // diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 7b09ffeb0..becfa7596 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -43,6 +43,7 @@ #include <stdint.h> #endif #include <unistd.h> +#include <errno.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> @@ -175,16 +176,15 @@ static XErrorHandler origErrorHandler = NULL ; static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e) { - fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X\n", dpy, e->error_code); + fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno)); - if (e->error_code == BadAtom) - { + if (e->error_code == BadAtom) { fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid); - } else if (e->error_code == BadWindow) - { + } else if (e->error_code == BadWindow) { fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid); } else { - NewtCommon_throwNewRuntimeException(x11ErrorHandlerJNIEnv, "NEWT X11 Error: Display %p, Code 0x%X", dpy, e->error_code); + NewtCommon_throwNewRuntimeException(x11ErrorHandlerJNIEnv, "NEWT X11 Error: Display %p, Code 0x%X, errno %s", + dpy, e->error_code, strerror(errno)); } return 0; @@ -197,8 +197,10 @@ static void displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) { origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler); } } else { - XSetErrorHandler(origErrorHandler); - origErrorHandler = NULL; + if(NULL!=origErrorHandler) { + XSetErrorHandler(origErrorHandler); + origErrorHandler = NULL; + } } } @@ -850,7 +852,6 @@ JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getAvailable int major, minor; if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getAvailableScreenModeRotations0: RANDR not available\n"); fprintf(stderr, "RANDR not available\n"); return (*env)->NewIntArray(env, 0); } @@ -897,7 +898,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModeR Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); return 0; } @@ -919,7 +920,7 @@ JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getScreenMod Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); return (*env)->NewIntArray(env, 0); } @@ -962,7 +963,7 @@ JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getScreenMod Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); return (*env)->NewIntArray(env, 0); } @@ -1006,7 +1007,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenR Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); return -1; } @@ -1032,7 +1033,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenR Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); return -1; } @@ -1061,7 +1062,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenR Window root = RootWindow(dpy, (int)scrn_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); return -1; } @@ -1080,24 +1081,20 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenR /* * Class: com_jogamp_newt_impl_x11_X11Screen - * Method: setScreenMode0 + * Method: setCurrentScreenModeStart0 * Signature: (JIIII)Z */ -JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenMode0 +JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenModeStart0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) { - int randr_event_base, randr_error_base; Display *dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT(stderr, "Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenMode0: RANDR not available\n"); + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n"); return JNI_FALSE; } - XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); - DBG_PRINT("RANDR: event_base: %d\n", randr_event_base); - int num_sizes; XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions XRRScreenConfiguration *conf; @@ -1134,12 +1131,48 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScr XSync(dpy, False); XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); XSync(dpy, False); - + + //free + XRRFreeScreenConfigInfo(conf); + XSync(dpy, False); + + return JNI_TRUE; +} + +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: setCurrentScreenModePollEnd0 + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenModePollEnd0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +{ + Display *dpy = (Display *) (intptr_t) display; + int randr_event_base, randr_error_base; XEvent evt; XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); + return 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); + } + + XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); + int done = 0; + int rot; do { - // XWindowEvent(dpy, root, randr_event_base + RRScreenChangeNotify, &evt); + if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { + return; + } XNextEvent(dpy, &evt); switch (evt.type - randr_event_base) { @@ -1160,11 +1193,8 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScr XRRUpdateConfiguration(&evt); } while(!done); - //free - XRRFreeScreenConfigInfo(conf); XSync(dpy, False); - return JNI_TRUE; } /** |