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/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java index 95136e9a7..0cf0adfc3 100644 --- a/core/src/processing/core/PShape.java +++ b/core/src/processing/core/PShape.java @@ -3024,9 +3024,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/PJOGL.java b/core/src/processing/opengl/PJOGL.java index c138bddd5..cfe58dc9f 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; @@ -128,6 +129,8 @@ public class PJOGL extends PGL { } + private static boolean forceSharedObjectSync = true; + /////////////////////////////////////////////////////////////// // Initialization, finalization @@ -183,6 +186,11 @@ public class PJOGL extends PGL { } + public boolean needSharedObjectSync() { + return forceSharedObjectSync || gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync); + } + + public void setFps(float fps) { if (!setFps || targetFps != fps) { if (60 < fps) { diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index 8f36aa592..2113b5299 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -3447,12 +3447,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/src/processing/opengl/PSurfaceJOGL.java b/core/src/processing/opengl/PSurfaceJOGL.java index 4b4910011..b35a8a9b4 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)); + } } } diff --git a/core/todo.txt b/core/todo.txt index d944a30b4..b77e61e6b 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -3,10 +3,16 @@ 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 +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) 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