From a9289ce0fde4d4d344e4ab895790642383226cb4 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 8 Sep 2011 03:53:33 +0200 Subject: NEWT/ScreenMode: X11 fixes ; Ensure Screen's size is set if screenMode changed ; Enhanced tests; Catch NV/XRANDR/GL bug X11 fixes - X11Screen properly uses it's display's connection decorated in lock/unlock (for ScreenMode etc) Ensure Screen's size is set if screenMode changed - ScreenImpl's ScreenModeListener updates it's screen size so 'external' changes will be detected. Enhanced tests - Verify more data rel. ScreenMode Catch NV/XRANDR/GL bug - Read TestScreenMode01NEWT/TestScreenMode01bNEWT comments --- src/newt/classes/jogamp/newt/DisplayImpl.java | 19 ++ src/newt/classes/jogamp/newt/ScreenImpl.java | 18 +- .../classes/jogamp/newt/driver/x11/X11Screen.java | 342 +++++++++++---------- src/newt/native/X11Window.c | 9 +- 4 files changed, 214 insertions(+), 174 deletions(-) (limited to 'src/newt') diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index ddb409338..92add6a4e 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -38,6 +38,7 @@ 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 com.jogamp.newt.util.MainThread; @@ -445,6 +446,24 @@ public abstract class DisplayImpl extends Display { } } + public interface DisplayRunnable { + Object run(long dpy); + } + public final Object runWithLockedDisplayHandle(DisplayRunnable action) { + final AbstractGraphicsDevice aDevice = getGraphicsDevice(); + if(null == aDevice) { + throw new RuntimeException("null device - not initialized: "+this); + } + Object res; + aDevice.lock(); + try { + res = action.run(aDevice.getHandle()); + } finally { + aDevice.unlock(); + } + return res; + } + protected EDTUtil edtUtil = null; protected int id; protected String name; diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index c83a82a7c..749bba114 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -169,16 +169,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")"); } t0 = System.currentTimeMillis(); - display.createNative(); // 1st display: trigger creation w/o incr ref count (hold native dispatching) - try { - createNativeImpl(); - if(null == aScreen) { - throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); - } - initScreenModeStatus(); - } finally { - display.addReference(); // 1st display: allow native dispatching + display.addReference(); + createNativeImpl(); + if(null == aScreen) { + throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); } + initScreenModeStatus(); if(DEBUG) { System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+")"); } @@ -322,7 +318,6 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { // if mode has changed somehow, update it .. if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) { - setScreenSize(smU.getRotatedWidth(), smU.getRotatedHeight()); sms.fireScreenModeChanged(smU, true); } } finally { @@ -391,6 +386,9 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { } public void screenModeChanged(ScreenMode sm, boolean success) { + if(success) { + setScreenSize(sm.getRotatedWidth(), sm.getRotatedHeight()); + } for(int i=0; i=res[0] || 0>=res[1]) { - throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number); - } - int bpp = 32; // FIXME - int rate = nrates[nrate_index]; - if(0>=rate) { - throw new InternalError("invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length); - } - 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++] = bpp; // bpp - 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 (int[]) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + // initialize iterators and static data + nrotations = getAvailableScreenModeRotations0(dpy, screen_idx); + if(null==nrotations || 0==nrotations.length) { return null; } - - nrates = getScreenModeRates0(getDisplayEDTHandle(), screen_idx, nres_index); + 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(); + } } ); + } - return props; + protected int[] getScreenModeNextImpl() { + // assemble: w x h x bpp x f x r + return (int[]) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object 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 bpp = 32; // FIXME + int rate = nrates[nrate_index]; + if(0>=rate) { + throw new InternalError("invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length); + } + 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++] = bpp; // bpp + 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() { - int resNumber = getNumScreenModeResolutions0(getDisplayEDTHandle(), screen_idx); - if(0==resNumber) { - return null; - } - int resIdx = getCurrentScreenResolutionIndex0(getDisplayEDTHandle(), screen_idx); - if(0>resIdx) { - return null; - } - if(resIdx>=resNumber) { - throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber); - } - int[] res = getScreenModeResolution0(getDisplayEDTHandle(), 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); - } - int rate = getCurrentScreenRate0(getDisplayEDTHandle(), screen_idx); - if(0>rate) { - return null; - } - int rot = getCurrentScreenRotation0(getDisplayEDTHandle(), screen_idx); - if(0>rot) { - return null; - } - - 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++] = 32; // FIXME: bpp - 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); + return (ScreenMode) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + int resNumber = getNumScreenModeResolutions0(dpy, screen_idx); + if(0==resNumber) { + return null; + } + int resIdx = getCurrentScreenResolutionIndex0(dpy, screen_idx); + if(0>resIdx) { + return null; + } + if(resIdx>=resNumber) { + throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber); + } + int[] 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); + } + int rate = getCurrentScreenRate0(dpy, screen_idx); + if(0>rate) { + return null; + } + int rot = getCurrentScreenRotation0(dpy, screen_idx); + if(0>rot) { + return null; + } + 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++] = 32; // FIXME: bpp + 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(ScreenMode screenMode) { - List screenModes = this.getScreenModesOrig(); - int screenModeIdx = screenModes.indexOf(screenMode); + 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); } - int resNumber = getNumScreenModeResolutions0(getDisplayEDTHandle(), 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 AbstractGraphicsDevice aDevice = display.getGraphicsDevice(); - if(null == aDevice) { - throw new RuntimeException("null device - not initialized: "+display); - } - aDevice.lock(); - boolean done = false; - long t0 = System.currentTimeMillis(); - try { - long dpy = aDevice.getHandle(); - 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) { - try { Thread.sleep(10); } catch (InterruptedException e) { } + final long t0 = System.currentTimeMillis(); + Boolean done = (Boolean) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() { + public Object run(long dpy) { + boolean done = false; + 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, 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 { - aDevice.unlock(); - } - - if(!done) { + return Boolean.valueOf(done); + } + }); + + if(!done.booleanValue()) { System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ (System.currentTimeMillis()-t0)+"ms"); } - return done; + return done.booleanValue(); } //---------------------------------------------------------------------- // Internals only - // - private final long getDisplayEDTHandle() { - return ((X11Display) display).getEDTHandle(); + // + private final Object runWithLockedDisplayHandle(DisplayRunnable action) { + return display.runWithLockedDisplayHandle(action); + // return runWithTempDisplayHandle(action); } + /** just here for testing some X11 RANDR bugs .. etc .. + private final Object runWithTempDisplayHandle(DisplayRunnable action) { + long dpy = X11Util.openDisplay(null); + if(0 == dpy) { + throw new RuntimeException("null device"); + } + Object res; + try { + res = action.run(dpy); + } finally { + X11Util.closeDisplay(dpy); + } + return res; + } */ + private static native long GetScreen0(long dpy, int scrn_idx); private static native int getWidth0(long display, int scrn_idx); diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 8d47f544a..092f3f7d3 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -910,14 +910,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 NewtCommon_FatalError(env, "invalid display connection.."); } - scrn = ScreenOfDisplay(dpy,screen_index); + scrn = ScreenOfDisplay(dpy, screen_index); if(scrn==NULL) { - scrn=DefaultScreenOfDisplay(dpy); + fprintf(stderr, "couldn't get screen idx %d\n", screen_index); } - if(scrn==NULL) { - fprintf(stderr, "couldn't get screen ..\n"); - } - DBG_PRINT("X11: X11Screen_GetScreen0 scrn %p DONE\n", scrn); + DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn); return (jlong) (intptr_t) scrn; } -- cgit v1.2.3