Skip to content

Commit e4fb3a8

Browse files
committed
trying to go straight on the EDT, see notes in core/README
1 parent 78e2d1b commit e4fb3a8

5 files changed

Lines changed: 89 additions & 154 deletions

File tree

core/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ We're removing `Applet` as the base class for `PApplet` and redoing the entire r
2626
#### Retina/HiDPI/2x drawing and displays
2727
* Documentation changes [here](https://github.com/processing/processing-docs/issues/170)
2828

29+
#### The Event Dispatch Thread
30+
The current source starts putting AWT (and Swing, if any) calls on the [EDT](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html), per Oracle's statements in Java's documentation. Actual rendering in the default renderer happens off the EDT, but the EDT is used to blit the image to the screen (or resize windows, etc). Looking for more consistent cross-platform results by doing this.
31+
2932
## The Mess
3033

3134
The rest of this document are my notes while I'm making changes.

core/src/processing/core/PApplet.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ public class PApplet implements PConstants {
204204
static final boolean DEBUG = false;
205205
// static final boolean DEBUG = true;
206206

207-
/** Default width and height for applet when not specified */
207+
/** Default width and height for sketch when not specified */
208208
static public final int DEFAULT_WIDTH = 100;
209209
static public final int DEFAULT_HEIGHT = 100;
210210

@@ -9341,8 +9341,8 @@ static public void main(final String mainClass) {
93419341
* the 'args' array when not null.
93429342
* @param mainClass name of the class to load (with package if any)
93439343
* @param args command line arguments to pass to the sketch's 'args' array.
9344-
* Note that this is *not* the same as the args passed to PApplet
9345-
* such as --display and others.
9344+
* Note that this is *not* the same as the args passed to (and
9345+
* understood by) PApplet such as --display.
93469346
*/
93479347
static public void main(final String mainClass, final String[] sketchArgs) {
93489348
String[] args = new String[] { mainClass };
@@ -9353,7 +9353,6 @@ static public void main(final String mainClass, final String[] sketchArgs) {
93539353
}
93549354

93559355

9356-
/*
93579356
static public void runSketch(final String[] args,
93589357
final PApplet constructedApplet) {
93599358
EventQueue.invokeLater(new Runnable() {
@@ -9362,11 +9361,15 @@ public void run() {
93629361
}
93639362
});
93649363
}
9365-
*/
93669364

93679365

9368-
static public void runSketch(final String[] args,
9369-
final PApplet constructedApplet) {
9366+
/**
9367+
* Moving this to the EDT for 3.0a6 because the main() messes with AWT
9368+
* components (or even Swing components, presumably). Hoping to get more
9369+
* consistent behavior across platforms and implementations.
9370+
*/
9371+
static protected void runSketchEDT(final String[] args,
9372+
final PApplet constructedApplet) {
93709373
// Supposed to help with flicker, but no effect on OS X.
93719374
// TODO IIRC this helped on Windows, but need to double check.
93729375
System.setProperty("sun.awt.noerasebackground", "true");

core/src/processing/core/PSurfaceAWT.java

Lines changed: 63 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/*
44
Part of the Processing project - http://processing.org
55
6-
Copyright (c) 2014 The Processing Foundation
6+
Copyright (c) 2014-15 The Processing Foundation
77
88
This library is free software; you can redistribute it and/or
99
modify it under the terms of the GNU Lesser General Public
@@ -104,8 +104,10 @@ public void componentResized(ComponentEvent e) {
104104

105105

106106
/**
107-
* Handle grabbing the focus from the parent applet. Other renderers can
108-
* override this if handling needs to be different.
107+
* Handle grabbing the focus on startup. Other renderers can override this
108+
* if handling needs to be different. For the AWT, the request is invoked
109+
* later on the EDT. Other implementations may not require that, so the
110+
* invokeLater() happens in here rather than requiring the caller to wrap it.
109111
*/
110112
public void requestFocus() {
111113
// for 2.0a6, moving this request to the EDT
@@ -198,72 +200,11 @@ public void addNotify() {
198200
}
199201

200202

201-
/*
202-
protected synchronized void render_example() {
203-
System.out.println("render(), bounds are " + getBounds());
204-
if (getBufferStrategy() == null) { // whole block [121222]
205-
System.out.println("creating a strategy");
206-
createBufferStrategy(2);
207-
}
208-
BufferStrategy strategy = getBufferStrategy();
209-
if (strategy == null) {
210-
return;
211-
}
212-
// Render single frame
213-
do {
214-
// The following loop ensures that the contents of the drawing buffer
215-
// are consistent in case the underlying surface was recreated
216-
do {
217-
Graphics draw = strategy.getDrawGraphics();
218-
//Insets i = getInsets();
219-
//int w = (int)(((double)(getWidth() - i.left - i.right))/2+0.5);
220-
//int h = (int)(((double)(getHeight() - i.top - i.bottom))/2+0.5);
221-
Insets i = new Insets(0, 0, 0, 0);
222-
int w = getWidth() / 2;
223-
int h = getHeight() / 2;
224-
225-
if (false) {
226-
draw.setColor(Color.YELLOW);
227-
draw.fillRect(i.left, i.top + h, w, getHeight() - h);
228-
draw.fillRect(i.left + w, i.top, getWidth() - w, h);
229-
draw.setColor(Color.BLACK);
230-
draw.fillRect(i.left, i.top, w, h);
231-
draw.fillRect(i.left + w, i.top + h, getWidth() - w, getHeight() - h);
232-
} else {
233-
draw.setColor(Color.WHITE);
234-
draw.fillRect(i.left, i.top, getWidth(), getHeight());
235-
236-
draw.setColor(Color.BLACK);
237-
draw.setFont(new Font("SansSerif", Font.PLAIN, 50));
238-
draw.drawString("this is some text", 50, 100);
239-
240-
// draw.setColor(Color.BLACK);
241-
// int mx = Math.max(getWidth(), getHeight());
242-
// for (int x = -getWidth(); x < getWidth(); x += 5) {
243-
// draw.drawLine(x, 0, x + mx, mx);
244-
// }
245-
}
246-
247-
draw.dispose();
248-
249-
// Repeat the rendering if the drawing buffer contents
250-
// were restored
251-
System.out.println("restored " + strategy.contentsRestored());
252-
} while (strategy.contentsRestored());
253-
254-
// Display the buffer
255-
System.out.println("showing");
256-
strategy.show();
257-
258-
// Repeat the rendering if the drawing buffer was lost
259-
System.out.println("lost " + strategy.contentsLost());
260-
System.out.println();
261-
} while (strategy.contentsLost());
262-
}
263-
*/
264-
265-
266203
protected synchronized void render() {
204+
if (!EventQueue.isDispatchThread()) {
205+
//throw new IllegalStateException("render() called outside the EDT");
206+
System.err.println("render() called outside the EDT");
207+
}
267208
// if (canvas == null) {
268209
// removeListeners(this);
269210
// canvas = new Canvas();
@@ -283,6 +224,13 @@ protected synchronized void render() {
283224
return;
284225
}
285226

227+
if (graphics.image == null) {
228+
if (PApplet.DEBUG) {
229+
new Exception("image is null, returning").printStackTrace(System.out);
230+
}
231+
return;
232+
}
233+
286234
// System.out.println("render(), canvas bounds are " + canvas.getBounds());
287235
if (canvas.getBufferStrategy() == null) { // whole block [121222]
288236
// System.out.println("creating a strategy");
@@ -321,83 +269,15 @@ protected synchronized void render() {
321269
}
322270

323271

324-
/*
325-
@Override
326-
public void update(Graphics screen) {
327-
paint(screen);
328-
}
329-
330-
331-
@Override
332-
public void paint(Graphics screen) {
333-
// int r = (int) random(10000);
334-
// System.out.println("into paint " + r);
335-
//super.paint(screen);
336-
337-
// ignore the very first call to paint, since it's coming
338-
// from the o.s., and the applet will soon update itself anyway.
339-
if (frameCount == 0) {
340-
// println("Skipping frame");
341-
// paint() may be called more than once before things
342-
// are finally painted to the screen and the thread gets going
343-
return;
344-
}
345-
// without ignoring the first call, the first several frames
346-
// are confused because paint() gets called in the midst of
347-
// the initial nextFrame() call, so there are multiple
348-
// updates fighting with one another.
349-
350-
// make sure the screen is visible and usable
351-
// (also prevents over-drawing when using PGraphicsOpenGL)
352-
353-
// if (useActive) {
354-
// return;
355-
// }
356-
357-
// if (insideDraw) {
358-
// new Exception().printStackTrace(System.out);
359-
// }
360-
if (!insideDraw && (g != null) && (g.image != null)) {
361-
if (useStrategy) {
362-
render();
363-
} else {
364-
// System.out.println("drawing to screen");
365-
//screen.drawImage(g.image, 0, 0, null); // not retina friendly
366-
screen.drawImage(g.image, 0, 0, width, height, null);
367-
}
368-
} else {
369-
debug(insideDraw + " " + g + " " + ((g != null) ? g.image : "-"));
370-
}
371-
}
372-
*/
373-
374-
375272
public void blit() {
376-
// System.out.println("blit");
377-
((SmoothCanvas) canvas).render(); // ??
378-
// canvas.repaint();
379-
/*
380-
if (canvas.getGraphicsConfiguration() != null) {
381-
GraphicsDevice device = canvas.getGraphicsConfiguration().getDevice();
382-
if (device != displayDevice) {
383-
System.out.println("display device changed from " + displayDevice + " to " + device);
384-
}
385-
}
386-
387-
if (useActive) {
388-
if (useStrategy) {
389-
render();
390-
} else {
391-
Graphics screen = canvas.getGraphics();
392-
if (screen != null) {
393-
screen.drawImage(g.image, 0, 0, sketch.width, sketch.height, null);
394-
}
273+
// Other folks taht call render() (i.e. paint()) are already on the EDT.
274+
// We need to be using the EDT since we're messing with the Canvas
275+
// object and BufferStrategy and friends.
276+
EventQueue.invokeLater(new Runnable() {
277+
public void run() {
278+
((SmoothCanvas) canvas).render();
395279
}
396-
} else {
397-
canvas.repaint();
398-
}
399-
// getToolkit().sync(); // force repaint now (proper method)
400-
*/
280+
});
401281
}
402282

403283

@@ -674,6 +554,8 @@ public void windowClosing(WindowEvent e) {
674554

675555

676556
private void setCanvasSize() {
557+
// System.out.format("setting canvas size %d %d%n", sketchWidth, sketchHeight);
558+
// new Exception().printStackTrace(System.out);
677559
int contentW = Math.max(sketchWidth, MIN_WINDOW_WIDTH);
678560
int contentH = Math.max(sketchHeight, MIN_WINDOW_HEIGHT);
679561

@@ -833,7 +715,16 @@ public void resumeThread() {
833715
// needs to resize the frame, which will resize the canvas, and so on...
834716
public void setSize(int wide, int high) {
835717
// System.out.format("frame visible %b, setSize(%d, %d) %n", frame.isVisible(), wide, high);
836-
// new Exception().printStackTrace(System.out);
718+
if (PApplet.DEBUG) {
719+
new Exception(String.format("setSize(%d, %d)", wide, high)).printStackTrace(System.out);
720+
}
721+
722+
if (wide == sketchWidth && high == sketchHeight) {
723+
if (PApplet.DEBUG) {
724+
new Exception("w/h unchanged " + wide + " " + high).printStackTrace(System.out);
725+
}
726+
return; // unchanged, don't rebuild everything
727+
}
837728

838729
sketchWidth = wide;
839730
sketchHeight = high;
@@ -1421,13 +1312,25 @@ public void run() { // not good to make this synchronized, locks things up
14211312
// animation thread yields to other running threads.
14221313
final int NO_DELAYS_PER_YIELD = 15;
14231314

1315+
/*
14241316
// If size un-initialized, might be a Canvas. Call setSize() here since
14251317
// we now have a parent object that this Canvas can use as a peer.
14261318
if (graphics.image == null) {
14271319
// System.out.format("it's null, sketchW/H already set to %d %d%n", sketchWidth, sketchHeight);
1428-
setSize(sketchWidth, sketchHeight);
1320+
try {
1321+
EventQueue.invokeAndWait(new Runnable() {
1322+
public void run() {
1323+
setSize(sketchWidth, sketchHeight);
1324+
}
1325+
});
1326+
} catch (InterruptedException ie) {
1327+
ie.printStackTrace();
1328+
} catch (InvocationTargetException ite) {
1329+
ite.printStackTrace();
1330+
}
14291331
// System.out.format(" but now, sketchW/H changed to %d %d%n", sketchWidth, sketchHeight);
14301332
}
1333+
*/
14311334

14321335
// un-pause the sketch and get rolling
14331336
sketch.start();
@@ -1443,13 +1346,26 @@ public void run() { // not good to make this synchronized, locks things up
14431346
// }
14441347

14451348
// render a single frame
1446-
// if (g != null) {
1349+
// try {
1350+
// EventQueue.invokeAndWait(new Runnable() {
1351+
// public void run() {
14471352
sketch.handleDraw();
1448-
// }
14491353

1354+
// EventQueue.invokeLater(new Runnable() {
1355+
// public void run() {
14501356
if (sketch.frameCount == 1) {
14511357
requestFocus();
14521358
}
1359+
// }
1360+
// });
1361+
1362+
// }
1363+
// });
1364+
// } catch (InterruptedException ie) {
1365+
// ie.printStackTrace();
1366+
// } catch (InvocationTargetException ite) {
1367+
// ite.getTargetException().printStackTrace();
1368+
// }
14531369

14541370
// wait for update & paint to happen before drawing next frame
14551371
// this is necessary since the drawing is sometimes in a

core/todo.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ X added --span option
7272
X play with improvements to full screen here
7373

7474

75+
_ split 'present' and 'full screen'?
76+
_ --full-screen causes considerable flicker at this point
77+
_ or split them when sketchWidth/Height are implemented?
78+
_ check on performance of the new EDT setup
79+
80+
7581
showstoppers
7682
_ static sketch with size() produces black window
7783
_ are we running on the EDT or not?
@@ -82,6 +88,9 @@ _ https://github.com/processing/processing/issues/3113
8288
_ static mode - no setup() / draw() - broken in OpenGL
8389
_ https://github.com/processing/processing/issues/3163
8490

91+
_ sketch window is not placed at correct location on restart
92+
_ https://github.com/processing/processing/issues/3125
93+
8594

8695
applet/sketch
8796
_ performance issues on OS X (might be threading due to Applet)

todo.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ X https://github.com/processing/processing/issues/3096
2727
X remove code that's moving the sketch path arg later
2828
X https://github.com/processing/processing/commit/0a14835e6f5f4766b022e73a8fe562318636727c
2929

30+
_ install/remove buttons not working
31+
_ https://github.com/processing/processing/issues/3172
32+
_ search the source for 'applet' references (i.e. SVG docs)
33+
3034
integration of pdex/debug
3135
o make the tabs have a default minimum size
3236
o multiple sizes as they get smaller (web browser style)

0 commit comments

Comments
 (0)