deal with some threading issues, remove init()

This commit is contained in:
Ben Fry
2015-06-21 21:23:05 -04:00
parent 527f21948f
commit 036446a2b0
4 changed files with 121 additions and 165 deletions
+65 -55
View File
@@ -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;
}
+29 -91
View File
@@ -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();
}
};
+16 -15
View File
@@ -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
View File
@@ -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