From 69d14ab6d73a4dccddb72ea15ac8b8ff5409dc91 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Sun, 5 Dec 2021 11:30:11 -0500 Subject: [PATCH 1/6] added needSharedObjectSync function to PJOGL --- core/src/processing/opengl/PJOGL.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/processing/opengl/PJOGL.java b/core/src/processing/opengl/PJOGL.java index c7c494be3..2bdc919d3 100644 --- a/core/src/processing/opengl/PJOGL.java +++ b/core/src/processing/opengl/PJOGL.java @@ -51,6 +51,7 @@ import com.jogamp.opengl.GLCapabilitiesImmutable; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLDrawable; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.glu.GLUtessellator; import com.jogamp.opengl.glu.GLUtessellatorCallbackAdapter; @@ -183,6 +184,11 @@ public class PJOGL extends PGL { } + public boolean needSharedObjectSync() { + return gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync); + } + + public void setFps(float fps) { if (!setFps || targetFps != fps) { if (60 < fps) { From 35293c03d9a3239724a79a17bd215484dd93b5a5 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Sun, 5 Dec 2021 11:45:48 -0500 Subject: [PATCH 2/6] Implemented necessary logic in PSurfaceJOGL to handle context sharing and object synchronization --- core/src/processing/opengl/PSurfaceJOGL.java | 106 ++++++++++++++----- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/core/src/processing/opengl/PSurfaceJOGL.java b/core/src/processing/opengl/PSurfaceJOGL.java index f8a6344da..8de676e19 100644 --- a/core/src/processing/opengl/PSurfaceJOGL.java +++ b/core/src/processing/opengl/PSurfaceJOGL.java @@ -39,6 +39,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -56,6 +57,7 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.WindowClosingProtocol; import com.jogamp.newt.Display; @@ -107,6 +109,11 @@ public class PSurfaceJOGL implements PSurface { protected NewtCanvasAWT canvas; + protected static GLAutoDrawable sharedDrawable; + protected static ArrayList animators = new ArrayList<>(); + private final static Object sharedSyncMutex = new Object(); + private Object syncMutex; + protected int windowScaleFactor; protected float[] currentPixelScale = { 0, 0 }; @@ -254,6 +261,29 @@ public class PSurfaceJOGL implements PSurface { caps.setBackgroundOpaque(true); caps.setOnscreen(true); pgl.setCaps(caps); + + if (sharedDrawable == null) { + // Create a shared drawable to enable context sharing across multiple GL windows + // https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/GLSharedContextSetter.html + sharedDrawable = GLDrawableFactory.getFactory(profile).createDummyAutoDrawable(null, true, caps, null); + sharedDrawable.display(); + } + } + + + // To properly deal with synchronization when context sharing across multiple drawables (windows), we need a + // synchronization mutex object to ensure that rendering of each frame completes in their respective animator thread: + // https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/GLSharedContextSetter.html#synchronization + private Object getSyncMutex(GLAutoDrawable drawable) { + pgl.getGL(drawable); + if (pgl.needSharedObjectSync()) { + syncMutex = sharedSyncMutex; + } else { + if (syncMutex == null) { + syncMutex = new Object(); + } + } + return syncMutex; } @@ -327,6 +357,8 @@ public class PSurfaceJOGL implements PSurface { window.setTopLevelSize((int) displayRect.getWidth(), (int) displayRect.getHeight()); } } + + window.setSharedAutoDrawable(sharedDrawable); } @@ -354,6 +386,7 @@ public class PSurfaceJOGL implements PSurface { } animator = new FPSAnimator(window, 60); + animators.add(animator); drawException = null; animator.setUncaughtExceptionHandler((animator, drawable, cause) -> { @@ -637,6 +670,10 @@ public class PSurfaceJOGL implements PSurface { drawExceptionHandler = null; } if (animator != null) { + // Stops all other animators to avoid exceptions when closing a window in a multiple window configuration + for (FPSAnimator ani: animators) { + if (ani != animator) ani.stop(); + } return animator.stop(); } else { return false; @@ -753,9 +790,13 @@ public class PSurfaceJOGL implements PSurface { public class DrawListener implements GLEventListener { + private boolean isInit = false; + public void display(GLAutoDrawable drawable) { + if (!isInit) return; + if (display.getEDTUtil().isCurrentThreadEDT()) { - // For an unknown reason, the first two frames of the animator run on + // For some unknown reason, a few frames of the animator run on // the EDT. For those, we just skip this draw call to avoid badness. return; } @@ -770,17 +811,19 @@ public class PSurfaceJOGL implements PSurface { } if (!sketch.finished) { - pgl.getGL(drawable); - int prevFrameCount = sketch.frameCount; - sketch.handleDraw(); - if (prevFrameCount == sketch.frameCount || sketch.finished) { - // This hack allows the FBO layer to be swapped normally even if - // the sketch is no looping or finished because it does not call draw(), - // otherwise background artifacts may occur (depending on the hardware/drivers). - pgl.beginRender(); - pgl.endRender(sketch.sketchWindowColor()); + synchronized (getSyncMutex(drawable)) { + pgl.getGL(drawable); + int prevFrameCount = sketch.frameCount; + sketch.handleDraw(); + if (prevFrameCount == sketch.frameCount || sketch.finished) { + // This hack allows the FBO layer to be swapped normally even if + // the sketch is no looping or finished because it does not call draw(), + // otherwise background artifacts may occur (depending on the hardware/drivers). + pgl.beginRender(); + pgl.endRender(sketch.sketchWindowColor()); + } + PGraphicsOpenGL.completeFinishedPixelTransfers(); } - PGraphicsOpenGL.completeFinishedPixelTransfers(); } if (sketch.exitCalled()) { @@ -796,24 +839,37 @@ public class PSurfaceJOGL implements PSurface { } public void init(GLAutoDrawable drawable) { - pgl.getGL(drawable); - pgl.init(drawable); - sketch.start(); + if (display.getEDTUtil().isCurrentThreadEDT()) { + return; + } - int c = graphics.backgroundColor; - pgl.clearColor(((c >> 16) & 0xff) / 255f, - ((c >> 8) & 0xff) / 255f, - (c & 0xff) / 255f, - ((c >> 24) & 0xff) / 255f); - pgl.clear(PGL.COLOR_BUFFER_BIT); + synchronized (getSyncMutex(drawable)) { + pgl.init(drawable); + sketch.start(); + + int c = graphics.backgroundColor; + pgl.clearColor(((c >> 16) & 0xff) / 255f, + ((c >> 8) & 0xff) / 255f, + (c & 0xff) / 255f, + ((c >> 24) & 0xff) / 255f); + pgl.clear(PGL.COLOR_BUFFER_BIT); + isInit = true; + } } public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { - pgl.resetFBOLayer(); - pgl.getGL(drawable); - float scale = PApplet.platform == PConstants.MACOS ? - getCurrentPixelScale() : getPixelScale(); - setSize((int) (w / scale), (int) (h / scale)); + if (!isInit) return; + + if (display.getEDTUtil().isCurrentThreadEDT()) { + return; + } + + synchronized (getSyncMutex(drawable)) { + pgl.resetFBOLayer(); + float scale = PApplet.platform == PConstants.MACOS ? + getCurrentPixelScale() : getPixelScale(); + setSize((int) (w / scale), (int) (h / scale)); + } } } From 29168df9281492904ef2930271abaae6497b3bfd Mon Sep 17 00:00:00 2001 From: codeanticode Date: Mon, 6 Dec 2021 00:23:10 -0500 Subject: [PATCH 3/6] Added field to force use of sync object --- core/src/processing/opengl/PJOGL.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/processing/opengl/PJOGL.java b/core/src/processing/opengl/PJOGL.java index 2bdc919d3..b149ac124 100644 --- a/core/src/processing/opengl/PJOGL.java +++ b/core/src/processing/opengl/PJOGL.java @@ -129,6 +129,8 @@ public class PJOGL extends PGL { } + private static boolean forceSharedObjectSync = true; + /////////////////////////////////////////////////////////////// // Initialization, finalization @@ -185,7 +187,7 @@ public class PJOGL extends PGL { public boolean needSharedObjectSync() { - return gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync); + return forceSharedObjectSync || gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync); } From b053e4d15a22e4992c3088de00365fd7c47435c1 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Mon, 6 Dec 2021 06:51:43 -0500 Subject: [PATCH 4/6] note about multi-window merge --- core/todo.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/todo.txt b/core/todo.txt index d944a30b4..f387b5a57 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -7,6 +7,10 @@ X added workaround in PShapeOpenGL to get access to vertex data _ still need to find the root cause _ also need to check for other reports about this +X multiple windows with GL +_ https://github.com/processing/processing4/issues/312 +X https://github.com/processing/processing4/pull/313 + _ made DrawListener public in PSurfaceJOGL (probably change that back) From 4eb0939a9ecee88cf00a509fc1ed612b3c007270 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Mon, 6 Dec 2021 13:18:48 -0500 Subject: [PATCH 5/6] adding intellij project files now that they have settled a wee bit --- .gitignore | 2 - app/processing4-app.iml | 60 ++++++ .../appbundler/processing4-appbundler.iml | 13 ++ .../processing4-tools-moviemaker.iml | 28 +++ .../ThemeEngine/processing4-tools-theme.iml | 29 +++ core/.gitignore | 1 - core/.idea/.gitignore | 3 + core/.idea/ant.xml | 6 + core/.idea/misc.xml | 6 + core/.idea/modules.xml | 9 + core/.idea/vcs.xml | 6 + core/methods/processing4-core-preproc.iml | 27 +++ core/processing4-core.iml | 12 ++ java/libraries/dxf/processing4-dxf.iml | 13 ++ java/libraries/javafx/processing4-javafx.iml | 35 ++++ java/libraries/net/processing4-net.iml | 13 ++ java/libraries/pdf/processing4-pdf.iml | 21 ++ java/libraries/serial/processing4-serial.iml | 28 +++ java/libraries/svg/processing4-svg.iml | 21 ++ java/processing4-java.iml | 181 ++++++++++++++++++ 20 files changed, 511 insertions(+), 3 deletions(-) create mode 100644 app/processing4-app.iml create mode 100644 build/macosx/appbundler/processing4-appbundler.iml create mode 100644 build/shared/tools/MovieMaker/processing4-tools-moviemaker.iml create mode 100644 build/shared/tools/ThemeEngine/processing4-tools-theme.iml create mode 100644 core/.idea/.gitignore create mode 100644 core/.idea/ant.xml create mode 100644 core/.idea/misc.xml create mode 100644 core/.idea/modules.xml create mode 100644 core/.idea/vcs.xml create mode 100644 core/methods/processing4-core-preproc.iml create mode 100644 core/processing4-core.iml create mode 100644 java/libraries/dxf/processing4-dxf.iml create mode 100644 java/libraries/javafx/processing4-javafx.iml create mode 100644 java/libraries/net/processing4-net.iml create mode 100644 java/libraries/pdf/processing4-pdf.iml create mode 100644 java/libraries/serial/processing4-serial.iml create mode 100644 java/libraries/svg/processing4-svg.iml create mode 100644 java/processing4-java.iml diff --git a/.gitignore b/.gitignore index 95436daf3..a18de53e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,11 @@ .DS_Store .AppleDouble -*.iml ._* *~ /build/shared/reference.zip *.x -# temporary, until we complete the move to IntelliJ #*.iml #/.idea diff --git a/app/processing4-app.iml b/app/processing4-app.iml new file mode 100644 index 000000000..b0634b773 --- /dev/null +++ b/app/processing4-app.iml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/macosx/appbundler/processing4-appbundler.iml b/build/macosx/appbundler/processing4-appbundler.iml new file mode 100644 index 000000000..c30dab7bf --- /dev/null +++ b/build/macosx/appbundler/processing4-appbundler.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/shared/tools/MovieMaker/processing4-tools-moviemaker.iml b/build/shared/tools/MovieMaker/processing4-tools-moviemaker.iml new file mode 100644 index 000000000..608b28585 --- /dev/null +++ b/build/shared/tools/MovieMaker/processing4-tools-moviemaker.iml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/shared/tools/ThemeEngine/processing4-tools-theme.iml b/build/shared/tools/ThemeEngine/processing4-tools-theme.iml new file mode 100644 index 000000000..2d35c6077 --- /dev/null +++ b/build/shared/tools/ThemeEngine/processing4-tools-theme.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/.gitignore b/core/.gitignore index 541feadb3..d2cc0abf0 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -1,6 +1,5 @@ bin bin-test -.idea /library/gluegen-rt*.jar /library/jogl-all*.jar diff --git a/core/.idea/.gitignore b/core/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/core/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/core/.idea/ant.xml b/core/.idea/ant.xml new file mode 100644 index 000000000..a2a476982 --- /dev/null +++ b/core/.idea/ant.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/.idea/misc.xml b/core/.idea/misc.xml new file mode 100644 index 000000000..1763e153b --- /dev/null +++ b/core/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/.idea/modules.xml b/core/.idea/modules.xml new file mode 100644 index 000000000..d5b4e612a --- /dev/null +++ b/core/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/core/.idea/vcs.xml b/core/.idea/vcs.xml new file mode 100644 index 000000000..6c0b86358 --- /dev/null +++ b/core/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/methods/processing4-core-preproc.iml b/core/methods/processing4-core-preproc.iml new file mode 100644 index 000000000..bea76e7d8 --- /dev/null +++ b/core/methods/processing4-core-preproc.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/processing4-core.iml b/core/processing4-core.iml new file mode 100644 index 000000000..129c87525 --- /dev/null +++ b/core/processing4-core.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/dxf/processing4-dxf.iml b/java/libraries/dxf/processing4-dxf.iml new file mode 100644 index 000000000..97b6e2863 --- /dev/null +++ b/java/libraries/dxf/processing4-dxf.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/javafx/processing4-javafx.iml b/java/libraries/javafx/processing4-javafx.iml new file mode 100644 index 000000000..e169dfb69 --- /dev/null +++ b/java/libraries/javafx/processing4-javafx.iml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/net/processing4-net.iml b/java/libraries/net/processing4-net.iml new file mode 100644 index 000000000..97b6e2863 --- /dev/null +++ b/java/libraries/net/processing4-net.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/pdf/processing4-pdf.iml b/java/libraries/pdf/processing4-pdf.iml new file mode 100644 index 000000000..5d6ac8011 --- /dev/null +++ b/java/libraries/pdf/processing4-pdf.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/serial/processing4-serial.iml b/java/libraries/serial/processing4-serial.iml new file mode 100644 index 000000000..0ca1d9326 --- /dev/null +++ b/java/libraries/serial/processing4-serial.iml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/libraries/svg/processing4-svg.iml b/java/libraries/svg/processing4-svg.iml new file mode 100644 index 000000000..484404723 --- /dev/null +++ b/java/libraries/svg/processing4-svg.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/processing4-java.iml b/java/processing4-java.iml new file mode 100644 index 000000000..e0c6cdc50 --- /dev/null +++ b/java/processing4-java.iml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From a62fe39ede7febec607a1f75ccb3ae6fe418e4dd Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Fri, 10 Dec 2021 15:16:29 -0500 Subject: [PATCH 6/6] allow GEOMETRY in addition to PATH for contains() --- core/src/processing/core/PShape.java | 4 +++- core/src/processing/opengl/PShapeOpenGL.java | 12 ++++++++---- core/todo.txt | 2 ++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java index ab3288c60..941638850 100644 --- a/core/src/processing/core/PShape.java +++ b/core/src/processing/core/PShape.java @@ -3023,9 +3023,11 @@ public class PShape implements PConstants { /** * Return true if this x, y coordinate is part of this shape. Only works * with PATH shapes or GROUP shapes that contain other GROUPs or PATHs. + * This method is not imperfect and doesn't account for all cases + * (not all complex shapes: concave shapes or holes may have issues). */ public boolean contains(float x, float y) { - if (family == PATH) { + if (family == PATH || family == GEOMETRY) { PVector p = new PVector(x, y); if (matrix != null) { // apply the inverse transformation matrix to the point coordinates diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index c471fe49d..c0d68c44f 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -2730,12 +2730,16 @@ public class PShapeOpenGL extends PShape { // - // Geometry utils - - // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + /** + * Return true if this x, y coordinate is part of this shape. Only works + * with PATH shapes or GROUP shapes that contain other GROUPs or PATHs. + * This method is not imperfect and doesn't account for all cases + * (not all complex shapes: concave shapes or holes may have issues). + */ @Override public boolean contains(float x, float y) { - if (family == PATH) { + if (family == PATH || family == GEOMETRY) { + // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html boolean c = false; for (int i = 0, j = inGeo.vertexCount-1; i < inGeo.vertexCount; j = i++) { if (((inGeo.vertices[3 * i + 1] > y) != (inGeo.vertices[3 * j + 1] > y)) && diff --git a/core/todo.txt b/core/todo.txt index f387b5a57..b77e61e6b 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -3,6 +3,8 @@ X support extensions for directories with listFiles/listPaths X otherwise asking for .jpg will return root folders (unless 'only files' specified) X but because macOS actually puts extensions on folders (.app, etc), support it X fix for disableStyle() with 2D shapes in P3D +X allow GEOMETRY (not just PATH) with contains() in PShape +X the method is still incomplete, but added a note about that too X added workaround in PShapeOpenGL to get access to vertex data _ still need to find the root cause _ also need to check for other reports about this