mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
deal with some threading issues, remove init()
This commit is contained in:
@@ -40,6 +40,7 @@ import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
|
||||
// used by loadImage() functions
|
||||
import javax.imageio.ImageIO;
|
||||
// allows us to remove our own MediaTracker code
|
||||
@@ -256,7 +257,7 @@ public class PApplet implements PConstants {
|
||||
* true if no size() command has been executed. This is used to wait until
|
||||
* a size has been set before placing in the window and showing it.
|
||||
*/
|
||||
public boolean defaultSize;
|
||||
// public boolean defaultSize;
|
||||
|
||||
// /** Storage for the current renderer size to avoid re-allocation. */
|
||||
// Dimension currentSize = new Dimension();
|
||||
@@ -507,7 +508,7 @@ public class PApplet implements PConstants {
|
||||
* across platforms and input methods.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean firstMouse;
|
||||
public boolean firstMouse = true;
|
||||
|
||||
/**
|
||||
* ( begin auto-generated from mouseButton.xml )
|
||||
@@ -706,10 +707,10 @@ public class PApplet implements PConstants {
|
||||
*/
|
||||
public float frameRate = 10;
|
||||
|
||||
protected boolean looping;
|
||||
protected boolean looping = true;
|
||||
|
||||
/** flag set to true when a redraw is asked for by the user */
|
||||
protected boolean redraw;
|
||||
protected boolean redraw = true;
|
||||
|
||||
/**
|
||||
* ( begin auto-generated from frameCount.xml )
|
||||
@@ -828,55 +829,55 @@ public class PApplet implements PConstants {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
/**
|
||||
* Applet initialization. This can do GUI work because the components have
|
||||
* not been 'realized' yet: things aren't visible, displayed, etc.
|
||||
*/
|
||||
public void init() {
|
||||
// println("init() called " + Integer.toHexString(hashCode()));
|
||||
// using a local version here since the class variable is deprecated
|
||||
// Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
// screenWidth = screen.width;
|
||||
// screenHeight = screen.height;
|
||||
|
||||
defaultSize = true;
|
||||
finished = false; // just for clarity
|
||||
|
||||
// this will be cleared by draw() if it is not overridden
|
||||
looping = true;
|
||||
redraw = true; // draw this guy at least once
|
||||
firstMouse = true;
|
||||
|
||||
// calculated dynamically on first call
|
||||
// // Removed in 2.1.2, brought back for 2.1.3. Usually sketchPath is set
|
||||
// // inside runSketch(), but if this sketch takes care of calls to init()
|
||||
// // when PApplet.main() is not used (i.e. it's in a Java application).
|
||||
// // THe path needs to be set here so that loadXxxx() functions work.
|
||||
// if (sketchPath == null) {
|
||||
// sketchPath = calcSketchPath();
|
||||
// }
|
||||
|
||||
// set during Surface.initFrame()
|
||||
// // Figure out the available display width and height.
|
||||
// // No major problem if this fails, we have to try again anyway in
|
||||
// // handleDraw() on the first (== 0) frame.
|
||||
// checkDisplaySize();
|
||||
|
||||
// // Set the default size, until the user specifies otherwise
|
||||
// int w = sketchWidth();
|
||||
// int h = sketchHeight();
|
||||
// defaultSize = (w == DEFAULT_WIDTH) && (h == DEFAULT_HEIGHT);
|
||||
// /**
|
||||
// * Applet initialization. This can do GUI work because the components have
|
||||
// * not been 'realized' yet: things aren't visible, displayed, etc.
|
||||
// */
|
||||
// public void init() {
|
||||
//// println("init() called " + Integer.toHexString(hashCode()));
|
||||
// // using a local version here since the class variable is deprecated
|
||||
//// Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
//// screenWidth = screen.width;
|
||||
//// screenHeight = screen.height;
|
||||
//
|
||||
// g = makeGraphics(w, h, sketchRenderer(), null, true);
|
||||
// // Fire component resize event
|
||||
// setSize(w, h);
|
||||
// setPreferredSize(new Dimension(w, h));
|
||||
// defaultSize = true;
|
||||
// finished = false; // just for clarity
|
||||
//
|
||||
// width = g.width;
|
||||
// height = g.height;
|
||||
|
||||
surface.startThread();
|
||||
}
|
||||
// // this will be cleared by draw() if it is not overridden
|
||||
// looping = true;
|
||||
// redraw = true; // draw this guy at least once
|
||||
// firstMouse = true;
|
||||
//
|
||||
// // calculated dynamically on first call
|
||||
//// // Removed in 2.1.2, brought back for 2.1.3. Usually sketchPath is set
|
||||
//// // inside runSketch(), but if this sketch takes care of calls to init()
|
||||
//// // when PApplet.main() is not used (i.e. it's in a Java application).
|
||||
//// // THe path needs to be set here so that loadXxxx() functions work.
|
||||
//// if (sketchPath == null) {
|
||||
//// sketchPath = calcSketchPath();
|
||||
//// }
|
||||
//
|
||||
// // set during Surface.initFrame()
|
||||
//// // Figure out the available display width and height.
|
||||
//// // No major problem if this fails, we have to try again anyway in
|
||||
//// // handleDraw() on the first (== 0) frame.
|
||||
//// checkDisplaySize();
|
||||
//
|
||||
//// // Set the default size, until the user specifies otherwise
|
||||
//// int w = sketchWidth();
|
||||
//// int h = sketchHeight();
|
||||
//// defaultSize = (w == DEFAULT_WIDTH) && (h == DEFAULT_HEIGHT);
|
||||
////
|
||||
//// g = makeGraphics(w, h, sketchRenderer(), null, true);
|
||||
//// // Fire component resize event
|
||||
//// setSize(w, h);
|
||||
//// setPreferredSize(new Dimension(w, h));
|
||||
////
|
||||
//// width = g.width;
|
||||
//// height = g.height;
|
||||
//
|
||||
// surface.startThread();
|
||||
// }
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
@@ -2368,7 +2369,7 @@ public class PApplet implements PConstants {
|
||||
// // Give up, instead set the new renderer and re-attempt setup()
|
||||
// return;
|
||||
// }
|
||||
defaultSize = false;
|
||||
// defaultSize = false;
|
||||
|
||||
} else { // frameCount > 0, meaning an actual draw()
|
||||
// update the current frameRate
|
||||
@@ -10119,7 +10120,7 @@ public class PApplet implements PConstants {
|
||||
sketch.windowColor = windowColor;
|
||||
}
|
||||
|
||||
PSurface surface = sketch.initSurface();
|
||||
final PSurface surface = sketch.initSurface();
|
||||
// sketch.initSurface(windowColor, displayIndex, fullScreen, spanDisplays);
|
||||
|
||||
/*
|
||||
@@ -10146,6 +10147,9 @@ public class PApplet implements PConstants {
|
||||
surface.placeWindow(location, editorLocation);
|
||||
}
|
||||
|
||||
// EventQueue.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
|
||||
// Helps avoid this code being duplicated 2x per surface class.
|
||||
// Andres is testing to make sure this doesn't cause trouble.
|
||||
if (sketch.getGraphics().displayable()) {
|
||||
@@ -10153,9 +10157,15 @@ public class PApplet implements PConstants {
|
||||
}
|
||||
|
||||
// not always running externally when in present mode
|
||||
if (external) {
|
||||
if (sketch.external) {
|
||||
surface.setupExternalMessages();
|
||||
}
|
||||
|
||||
//sketch.init();
|
||||
surface.startThread();
|
||||
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
@@ -10220,7 +10230,7 @@ public class PApplet implements PConstants {
|
||||
surface.initOffscreen(this); // for PDF/PSurfaceNone and friends
|
||||
}
|
||||
|
||||
init();
|
||||
// init();
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@ public class PSurfaceAWT extends PSurfaceNone {
|
||||
private Dimension newSize = new Dimension(0, 0);
|
||||
|
||||
|
||||
// Turns out getParent() returns a JPanel on a JFrame. Yech.
|
||||
public Frame getFrame() {
|
||||
return frame;
|
||||
}
|
||||
@@ -197,7 +198,11 @@ public class PSurfaceAWT extends PSurfaceNone {
|
||||
// System.out.println("validate() render old=" + oldSize + " -> new=" + newSize);
|
||||
oldSize = newSize;
|
||||
sketch.setSize(newSize.width, newSize.height);
|
||||
// try {
|
||||
render();
|
||||
// } catch (IllegalStateException ise) {
|
||||
// System.out.println(ise.getMessage());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,103 +253,35 @@ public class PSurfaceAWT extends PSurfaceNone {
|
||||
|
||||
|
||||
synchronized protected void render() {
|
||||
// System.out.println("render() top");
|
||||
|
||||
/*
|
||||
if (!EventQueue.isDispatchThread()) {
|
||||
//throw new IllegalStateException("render() called outside the EDT");
|
||||
//System.err.println("render() called outside the EDT");
|
||||
new Exception("render() called outside the EDT").printStackTrace();
|
||||
if (canvas.isDisplayable() &&
|
||||
graphics.image != null) {
|
||||
if (canvas.getBufferStrategy() == null) {
|
||||
canvas.createBufferStrategy(2);
|
||||
}
|
||||
*/
|
||||
// if (canvas == null) {
|
||||
// removeListeners(this);
|
||||
// canvas = new Canvas();
|
||||
// add(canvas);
|
||||
// setIgnoreRepaint(true);
|
||||
// canvas.setIgnoreRepaint(true);
|
||||
// addListeners(canvas);
|
||||
//// add(canvas, BorderLayout.CENTER);
|
||||
//// doLayout();
|
||||
// }
|
||||
BufferStrategy strategy = canvas.getBufferStrategy();
|
||||
if (strategy != null) {
|
||||
// Render single frame
|
||||
// try {
|
||||
do {
|
||||
// The following loop ensures that the contents of the drawing buffer
|
||||
// are consistent in case the underlying surface was recreated
|
||||
do {
|
||||
Graphics2D draw = (Graphics2D) strategy.getDrawGraphics();
|
||||
// draw to width/height, since this may be a 2x image
|
||||
draw.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
|
||||
draw.dispose();
|
||||
} while (strategy.contentsRestored());
|
||||
|
||||
// not sure why this was here, can't be good
|
||||
//canvas.setBounds(0, 0, sketch.width, sketch.height);
|
||||
// Display the buffer
|
||||
strategy.show();
|
||||
|
||||
if (!canvas.isDisplayable()) {
|
||||
// System.out.println("no peer.. holding");
|
||||
return;
|
||||
}
|
||||
|
||||
if (graphics.image == null) {
|
||||
if (PApplet.DEBUG) {
|
||||
new Exception("image is null, returning").printStackTrace(System.out);
|
||||
// Repeat the rendering if the drawing buffer was lost
|
||||
} while (strategy.contentsLost());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Canvas c = canvas;
|
||||
// Frame c = frame;
|
||||
// System.out.println("render(), canvas bounds are " + canvas.getBounds());
|
||||
if (c.getBufferStrategy() == null) { // whole block [121222]
|
||||
// System.out.println("creating a strategy");
|
||||
c.createBufferStrategy(2);
|
||||
}
|
||||
BufferStrategy strategy = c.getBufferStrategy();
|
||||
// System.out.println(strategy);
|
||||
if (strategy == null) {
|
||||
return;
|
||||
}
|
||||
// Render single frame
|
||||
do {
|
||||
// The following loop ensures that the contents of the drawing buffer
|
||||
// are consistent in case the underlying surface was recreated
|
||||
do {
|
||||
Graphics2D draw = (Graphics2D) strategy.getDrawGraphics();
|
||||
//draw.drawImage(pg.image, 0, 0, sketch.width, sketch.height, null);
|
||||
//System.out.println("render() drawing image");
|
||||
/*
|
||||
while (sketch.insideDraw) {
|
||||
System.out.println("render() yielding because inside draw");
|
||||
//Thread.yield();
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
*/
|
||||
|
||||
// this wasn't any faster than setting the image size while drawing
|
||||
// if (graphics.pixelFactor == 2) {
|
||||
// draw.scale(0.5, 0.5);
|
||||
// }
|
||||
|
||||
// draw to width/height, since this may be a 2x image
|
||||
draw.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
|
||||
// draw.drawImage(graphics.image, 0, 0, null);
|
||||
draw.dispose();
|
||||
|
||||
// Repeat the rendering if the drawing buffer contents
|
||||
// were restored
|
||||
// System.out.println("restored " + strategy.contentsRestored());
|
||||
} while (strategy.contentsRestored());
|
||||
|
||||
// Display the buffer
|
||||
// System.out.println("showing");
|
||||
strategy.show();
|
||||
|
||||
// Repeat the rendering if the drawing buffer was lost
|
||||
// System.out.println("lost " + strategy.contentsLost());
|
||||
// System.out.println();
|
||||
} while (strategy.contentsLost());
|
||||
// System.out.println("render() bottom");
|
||||
}
|
||||
|
||||
|
||||
// Object offscreenLock = new Object();
|
||||
// BufferedImage offscreen;
|
||||
// BufferedImage onscreen;
|
||||
|
||||
|
||||
/*
|
||||
protected void blit() {
|
||||
// Other folks that call render() (i.e. paint()) are already on the EDT.
|
||||
@@ -762,8 +699,10 @@ public class PSurfaceAWT extends PSurfaceNone {
|
||||
//frame.setExtendedState(Frame.MAXIMIZED_BOTH);
|
||||
|
||||
// https://github.com/processing/processing/pull/3162
|
||||
frame.dispose(); // release native resources, allows setUndecorated()
|
||||
//frame.dispose(); // release native resources, allows setUndecorated()
|
||||
frame.removeNotify();
|
||||
frame.setUndecorated(true);
|
||||
frame.addNotify();
|
||||
|
||||
// this may be the bounds of all screens
|
||||
frame.setBounds(screenRect);
|
||||
@@ -1479,7 +1418,6 @@ public class PSurfaceAWT extends PSurfaceNone {
|
||||
@Override
|
||||
public void callDraw() {
|
||||
sketch.handleDraw();
|
||||
//blit();
|
||||
render();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -493,21 +493,22 @@ public class PSurfaceJOGL implements PSurface {
|
||||
|
||||
|
||||
public void startThread() {
|
||||
if (animator == null) return;
|
||||
if (placedWindow) {
|
||||
window.setVisible(true);
|
||||
animator.start();
|
||||
requestedStart = false;
|
||||
} else {
|
||||
// The GL window is not visible until it has been placed, so we cannot
|
||||
// start the animator because it requires the window to be visible.
|
||||
requestedStart = true;
|
||||
// Need this assignment to bypass the while loop in runSketch, otherwise
|
||||
// the programs hangs waiting for defaultSize to be false, but it never
|
||||
// happens because the animation thread is not yet running to avoid showing
|
||||
// the window in the wrong place:
|
||||
// https://github.com/processing/processing/issues/3308
|
||||
sketch.defaultSize = false;
|
||||
if (animator != null) {
|
||||
if (placedWindow) {
|
||||
window.setVisible(true);
|
||||
animator.start();
|
||||
requestedStart = false;
|
||||
} else {
|
||||
// The GL window is not visible until it has been placed, so we cannot
|
||||
// start the animator because it requires the window to be visible.
|
||||
requestedStart = true;
|
||||
// Need this assignment to bypass the while loop in runSketch, otherwise
|
||||
// the programs hangs waiting for defaultSize to be false, but it never
|
||||
// happens because the animation thread is not yet running to avoid showing
|
||||
// the window in the wrong place:
|
||||
// https://github.com/processing/processing/issues/3308
|
||||
// sketch.defaultSize = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-4
@@ -54,6 +54,12 @@ X https://github.com/processing/processing/issues/3316
|
||||
X Window never shows with exported application on 64-bit Linux
|
||||
X https://github.com/processing/processing/issues/3303
|
||||
X present mode is now broken
|
||||
o still some spinning when sketches break
|
||||
X fixed because we're back off the EDT
|
||||
o settings() is probably not showing exceptions since we're back to the EDT
|
||||
o can't call handleSettings() on the anim thread since it sets the surface
|
||||
o so maybe the first part is on the EDT, but other threads run this stuff
|
||||
X remove the init() method
|
||||
|
||||
cleaning
|
||||
o possible addition for 'implementation' variable
|
||||
@@ -109,10 +115,9 @@ _ update wiki/docs to say "don't override sketchXxxx() methods"
|
||||
|
||||
|
||||
beta
|
||||
_ still some spinning when sketches break
|
||||
_ settings() is probably not showing exceptions since we're back to the EDT
|
||||
_ can't call handleSettings() on the anim thread since it sets the surface
|
||||
_ so maybe the first part is on the EDT, but other threads run this stuff
|
||||
_ run only the necessary pieces on the EDT
|
||||
_ in part because FX doesn't even use the EDT
|
||||
_ re-check the Linux frame visibility stuff
|
||||
_ try using Frame instead of JFrame
|
||||
_ default sketch location using insets incorrectly
|
||||
_ use the BufferStrategy directly from the Frame object?
|
||||
@@ -149,6 +154,8 @@ _ or pass createImage() through to renderer?
|
||||
_ implement frameRate()
|
||||
_ implement external messages (moving the window)
|
||||
_ implement PSurfaceFX.setIcon()
|
||||
_ javafx not supported with ARM (so we're screwed on raspberry pi)
|
||||
_ https://www.linkedin.com/pulse/oracle-just-removed-javafx-support-arm-jan-snelders
|
||||
|
||||
|
||||
opengl
|
||||
|
||||
Reference in New Issue
Block a user