diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 3f7a49649..3e9662668 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -32,10 +32,10 @@ package com.jme3.system.lwjgl; +import static com.jme3.util.LWJGLBufferAllocator.PROPERTY_CONCURRENT_BUFFER_ALLOCATOR; import static org.lwjgl.opencl.CL10.CL_CONTEXT_PLATFORM; import static org.lwjgl.opengl.GL.createCapabilities; import static org.lwjgl.opengl.GL11.glGetInteger; - import com.jme3.input.lwjgl.GlfwJoystickInput; import com.jme3.input.lwjgl.GlfwKeyInput; import com.jme3.input.lwjgl.GlfwMouseInput; @@ -52,24 +52,14 @@ import com.jme3.renderer.lwjgl.LwjglGL; import com.jme3.renderer.lwjgl.LwjglGLExt; import com.jme3.renderer.lwjgl.LwjglGLFboEXT; import com.jme3.renderer.lwjgl.LwjglGLFboGL3; -import com.jme3.renderer.opengl.GL; -import com.jme3.renderer.opengl.GL2; -import com.jme3.renderer.opengl.GL3; -import com.jme3.renderer.opengl.GL4; -import com.jme3.renderer.opengl.GLDebugDesktop; -import com.jme3.renderer.opengl.GLExt; -import com.jme3.renderer.opengl.GLFbo; -import com.jme3.renderer.opengl.GLRenderer; -import com.jme3.renderer.opengl.GLTiming; -import com.jme3.renderer.opengl.GLTimingState; -import com.jme3.renderer.opengl.GLTracer; +import com.jme3.renderer.opengl.*; import com.jme3.system.AppSettings; import com.jme3.system.JmeContext; import com.jme3.system.SystemListener; import com.jme3.system.Timer; import com.jme3.util.BufferAllocatorFactory; import com.jme3.util.LWJGLBufferAllocator; - +import com.jme3.util.LWJGLBufferAllocator.ConcurrentLWJGLBufferAllocator; import org.lwjgl.PointerBuffer; import org.lwjgl.glfw.GLFW; import org.lwjgl.opencl.APPLEGLSharing; @@ -96,9 +86,15 @@ public abstract class LwjglContext implements JmeContext { private static final Logger logger = Logger.getLogger(LwjglContext.class.getName()); static { + final String implementation = BufferAllocatorFactory.PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION; - if(System.getProperty(implementation) == null) { - System.setProperty(implementation, LWJGLBufferAllocator.class.getName()); + + if (System.getProperty(implementation) == null) { + if (Boolean.parseBoolean(System.getProperty(PROPERTY_CONCURRENT_BUFFER_ALLOCATOR, "true"))) { + System.setProperty(implementation, ConcurrentLWJGLBufferAllocator.class.getName()); + } else { + System.setProperty(implementation, LWJGLBufferAllocator.class.getName()); + } } } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java index 25fafabd2..b9080a57d 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java @@ -7,6 +7,7 @@ import java.lang.ref.ReferenceQueue; import java.nio.*; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.StampedLock; import java.util.logging.Logger; /** @@ -18,10 +19,49 @@ public class LWJGLBufferAllocator implements BufferAllocator { private static final Logger LOGGER = Logger.getLogger(LWJGLBufferAllocator.class.getName()); + public static final String PROPERTY_CONCURRENT_BUFFER_ALLOCATOR = "com.jme3.lwjgl3.ConcurrentBufferAllocator"; + + /** + * Threadsafe implementation of the {@link LWJGLBufferAllocator}. + * + * @author JavaSaBr + */ + public static class ConcurrentLWJGLBufferAllocator extends LWJGLBufferAllocator { + + /** + * The synchronizer. + */ + private final StampedLock stampedLock; + + public ConcurrentLWJGLBufferAllocator() { + this.stampedLock = new StampedLock(); + } + + @Override + public void destroyDirectBuffer(final Buffer buffer) { + final long stamp = stampedLock.writeLock(); + try { + super.destroyDirectBuffer(buffer); + } finally { + stampedLock.unlockWrite(stamp); + } + } + + @Override + public ByteBuffer allocate(final int size) { + final long stamp = stampedLock.writeLock(); + try { + return super.allocate(size); + } finally { + stampedLock.unlockWrite(stamp); + } + } + } + /** * The reference queue. */ - private static final ReferenceQueue DUMMY_QUEUE = new ReferenceQueue(); + private static final ReferenceQueue DUMMY_QUEUE = new ReferenceQueue<>(); /** * The LWJGL byte buffer deallocator. @@ -76,7 +116,7 @@ public class LWJGLBufferAllocator implements BufferAllocator { */ private static void freeByteBuffers() { try { - for (; ; ) { + for (;;) { final Deallocator deallocator = (Deallocator) DUMMY_QUEUE.remove(); deallocator.free(); }