diff options
author | Sven Göthel <[email protected]> | 2024-01-25 09:53:30 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-25 09:53:30 +0100 |
commit | 8fe39d3a524e5e580cf2667988965f1e27fed95b (patch) | |
tree | c7630c970b23ad5f6a2a5665cd8838a04b05aa58 /src/jogl/classes | |
parent | 78812de21182e32f86a823321b017f7f6cf52ae3 (diff) |
Bug 1491: GLMediaPlayerImpl: Use a shared *GraphicsDevice for all compatible shared GLContext, removing resource restrictions
In a use case with hundreds of GLMediaPlayer instances,
this causes the application to bail out due to running out of resources.
+++
GLMediaPlayer exposes resource restrictions and locking related
with the created off-thread shared GLContext
due to its newly created NativeWindow *GraphicsDevice instance (on X11).
On the X11 platform, the *GraphicsDevice actually uses a native resource (X11 Display handle) and hence creating such device is costly and limited.
To operate an off-thread GLContext w/o actual X11 input handling,
it is *NOT* required to use a new instance.
+++
Further more, the device is using locking.
To operate an off-thread GLContext, it is *NOT* required to use locking on it
as it does not perform actual X11 input handling etc.
All operations are performed on the shared GL context.
+++
Solution is to create a shared non-locking device clone
compatible with the source.
A share counter shall determine that the last one actually gets destructed.
The usual ..
Diffstat (limited to 'src/jogl/classes')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index 4a7e52c4f..2c916dddc 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -38,6 +38,8 @@ import java.util.Iterator; import java.util.Map; import com.jogamp.nativewindow.AbstractGraphicsDevice; +import com.jogamp.nativewindow.DefaultGraphicsDevice; +import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2GL3; import com.jogamp.opengl.GLContext; @@ -1457,7 +1459,17 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { final AbstractGraphicsDevice device = dummyDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); dummyDrawable.setRealized(false); dummyDrawable = null; - device.close(); + synchronized( singleLock ) { + if( singleDEBUG ) { System.err.println("ZZZ: device "+singleCount+": "+device.getClass()+", "+device); } + if( device == singleDevice && 0 == --singleCount ) { + DefaultGraphicsDevice.swapHandleAndOwnership(singleOwner, singleDevice); + if( singleDEBUG ) { + System.err.println("ZZZ: singleOwner "+singleOwner.getClass()+", "+singleOwner); + System.err.println("ZZZ: singleDevice "+singleDevice.getClass()+", "+singleDevice); + } + device.close(); + } + } } } @@ -1469,8 +1481,29 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { final boolean glCtxCurrent = glCtx.isCurrent(); final GLProfile glp = gl.getGLProfile(); final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - final AbstractGraphicsDevice device = glCtx.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); - dummyDrawable = factory.createDummyDrawable(device, true, glCtx.getGLDrawable().getChosenGLCapabilities(), null); // own device! + boolean createNewDevice = true; + AbstractGraphicsDevice device = glCtx.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + synchronized( singleLock ) { + if( null == singleOwner || singleOwner.getUniqueID().equals(device.getUniqueID()) ) { + if( null == singleOwner ) { + singleDevice = (DefaultGraphicsDevice) NativeWindowFactory.createDevice(device.getType(), device.getConnection(), device.getUnitID(), true); + singleOwner = new DefaultGraphicsDevice(singleDevice.getType(), singleDevice.getConnection(), singleDevice.getUnitID(), singleDevice.getHandle(), null); + DefaultGraphicsDevice.swapHandleAndOwnership(singleOwner, singleDevice); + if( singleDEBUG ) { + System.err.println("XXX: origDevice "+device.getClass()+", "+device); + System.err.println("XXX: singleOwner "+singleOwner.getClass()+", "+singleOwner); + System.err.println("XXX: singleDevice "+singleDevice.getClass()+", "+singleDevice); + } + } + createNewDevice = false; + device = singleDevice; + ++singleCount; + if( singleDEBUG ) { System.err.println("XXX: singleDevice "+singleCount+": "+device.getClass()+", "+device); } + } else { + if( singleDEBUG ) { System.err.println("XXX: createDevice from "+device.getClass()+", "+device); } + } + } + dummyDrawable = factory.createDummyDrawable(device, createNewDevice, glCtx.getGLDrawable().getChosenGLCapabilities(), null); dummyDrawable.setRealized(true); sharedGLCtx = dummyDrawable.createContext(glCtx); hasSharedGLCtx = null != sharedGLCtx; @@ -1598,6 +1631,11 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } private volatile StreamWorker streamWorker = null; private StreamException streamErr = null; + private static final boolean singleDEBUG = false; + private static final Object singleLock = new Object(); + private static DefaultGraphicsDevice singleDevice = null; + private static DefaultGraphicsDevice singleOwner = null; + private static int singleCount = 0; protected final GLMediaPlayer.EventMask addStateEventMask(final GLMediaPlayer.EventMask eventMask, final State newState) { if( state != newState ) { |