@@ -48,12 +48,11 @@ public class PSurfaceAWT extends PSurfaceBasic {
4848 // Note that x and y may not be zero, depending on the display configuration
4949 Rectangle screenRect ;
5050
51- // disabled on retina inside init()
52- boolean useActive = true ;
53- // boolean useActive = false;
54- // boolean useStrategy = true;
55- boolean useStrategy = false ;
56- Canvas canvas ;
51+ // 3.0a5 didn't use strategy, and active was shut off during init() w/ retina
52+ boolean useStrategy = true ;
53+
54+ // Canvas canvas;
55+ Component canvas ;
5756
5857 PGraphics graphics ;
5958
@@ -65,22 +64,31 @@ public PSurfaceAWT(PGraphics graphics) {
6564 this .graphics = graphics ;
6665
6766 if (checkRetina ()) {
67+ // System.out.println("retina in use");
68+
6869 // The active-mode rendering seems to be 2x slower, so disable it
6970 // with retina. On a non-retina machine, however, useActive seems
7071 // the only (or best) way to handle the rendering.
71- useActive = false ;
72+ // useActive = false;
73+ // canvas = new JPanel(true) {
74+ // @Override
75+ // public void paint(Graphics screen) {
76+ //// if (!sketch.insideDraw) {
77+ // screen.drawImage(PSurfaceAWT.this.graphics.image, 0, 0, sketchWidth, sketchHeight, null);
78+ //// }
79+ // }
80+ // };
81+ // Under 1.8 and the current 3.0a6 threading regime, active mode w/o
82+ // strategy is far faster, but perhaps only because it's blitting with
83+ // flicker--pushing pixels out before the screen has finished rendering.
84+ // useStrategy = false;
7285 }
73-
74- createCanvas ();
75- addListeners ();
76- }
77-
78-
79- void createCanvas () {
8086 canvas = new SmoothCanvas ();
81- canvas .setIgnoreRepaint (true ); // ??
87+ if (useStrategy ) {
88+ canvas .setIgnoreRepaint (true );
89+ }
8290
83- // send tab keys through to the PApplet
91+ // Pass tab key to the sketch, rather than moving between components
8492 canvas .setFocusTraversalKeysEnabled (false );
8593
8694 canvas .addComponentListener (new ComponentAdapter () {
@@ -91,6 +99,7 @@ public void componentResized(ComponentEvent e) {
9199 }
92100 }
93101 });
102+ addListeners ();
94103 }
95104
96105
@@ -177,28 +186,48 @@ public void update(Graphics g) {
177186
178187
179188 @ Override
180- public void paint (Graphics g ) {
189+ public void paint (Graphics screen ) {
181190// System.out.println("painting");
182191// validate();
183- render ();
192+ if (useStrategy ) {
193+ render ();
194+
195+ } else {
196+ // new Exception("painting").printStackTrace(System.out);
197+ // if (graphics.image != null) { // && !sketch.insideDraw) {
198+ if (onscreen != null ) {
199+ // synchronized (graphics.image) {
200+ // Needs the width/height to be set so that retina images are properly scaled down
201+ // screen.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
202+ synchronized (offscreenLock ) {
203+ screen .drawImage (onscreen , 0 , 0 , sketchWidth , sketchHeight , null );
204+ }
205+ }
206+ }
184207 }
185208
186209
210+ /*
187211 @Override
188212 public void addNotify() {
189213// System.out.println("adding notify");
190214 super.addNotify();
191215 // prior to Java 7 on OS X, this no longer works [121222]
192216// createBufferStrategy(2);
193217 }
218+ */
194219
195220
196221 protected synchronized void render () {
222+ //System.out.println("render() top");
223+
224+ /*
197225 if (!EventQueue.isDispatchThread()) {
198226 //throw new IllegalStateException("render() called outside the EDT");
199227 //System.err.println("render() called outside the EDT");
200228 new Exception("render() called outside the EDT").printStackTrace();
201229 }
230+ */
202231// if (canvas == null) {
203232// removeListeners(this);
204233// canvas = new Canvas();
@@ -225,12 +254,13 @@ protected synchronized void render() {
225254 return ;
226255 }
227256
257+ Canvas c = (Canvas ) canvas ;
228258// System.out.println("render(), canvas bounds are " + canvas.getBounds());
229- if (canvas .getBufferStrategy () == null ) { // whole block [121222]
259+ if (c .getBufferStrategy () == null ) { // whole block [121222]
230260// System.out.println("creating a strategy");
231- canvas .createBufferStrategy (2 );
261+ c .createBufferStrategy (2 );
232262 }
233- BufferStrategy strategy = canvas .getBufferStrategy ();
263+ BufferStrategy strategy = c .getBufferStrategy ();
234264// System.out.println(strategy);
235265 if (strategy == null ) {
236266 return ;
@@ -240,10 +270,27 @@ protected synchronized void render() {
240270 // The following loop ensures that the contents of the drawing buffer
241271 // are consistent in case the underlying surface was recreated
242272 do {
243- Graphics draw = strategy .getDrawGraphics ();
273+ Graphics2D draw = ( Graphics2D ) strategy .getDrawGraphics ();
244274 //draw.drawImage(pg.image, 0, 0, sketch.width, sketch.height, null);
275+ //System.out.println("render() drawing image");
276+ /*
277+ while (sketch.insideDraw) {
278+ System.out.println("render() yielding because inside draw");
279+ //Thread.yield();
280+ try {
281+ Thread.sleep(1);
282+ } catch (InterruptedException e) { }
283+ }
284+ */
285+
286+ // this wasn't any faster than setting the image size while drawing
287+ // if (graphics.pixelFactor == 2) {
288+ // draw.scale(0.5, 0.5);
289+ // }
290+
245291 // draw to width/height, since this may be a 2x image
246292 draw .drawImage (graphics .image , 0 , 0 , sketchWidth , sketchHeight , null );
293+ // draw.drawImage(graphics.image, 0, 0, null);
247294 draw .dispose ();
248295
249296 // Repeat the rendering if the drawing buffer contents
@@ -259,20 +306,56 @@ protected synchronized void render() {
259306// System.out.println("lost " + strategy.contentsLost());
260307// System.out.println();
261308 } while (strategy .contentsLost ());
309+ //System.out.println("render() bottom");
262310 }
263311 }
264312
265313
314+ Object offscreenLock = new Object ();
315+ BufferedImage offscreen ;
316+ BufferedImage onscreen ;
317+ // Graphics off;
318+
266319 @ Override
267320 public void blit () {
268- // Other folks taht call render() (i.e. paint()) are already on the EDT.
321+ // Other folks that call render() (i.e. paint()) are already on the EDT.
269322 // We need to be using the EDT since we're messing with the Canvas
270323 // object and BufferStrategy and friends.
271- EventQueue .invokeLater (new Runnable () {
272- public void run () {
273- ((SmoothCanvas ) canvas ).render ();
324+ //EventQueue.invokeLater(new Runnable() {
325+ //public void run() {
326+ //((SmoothCanvas) canvas).render();
327+ //}
328+ //});
329+
330+ if (useStrategy ) {
331+ // Not necessary to be on the EDT to update BufferStrategy
332+ ((SmoothCanvas ) canvas ).render ();
333+ } else {
334+ if (graphics .image != null ) {
335+ BufferedImage graphicsImage = (BufferedImage ) graphics .image ;
336+ if (offscreen == null ||
337+ offscreen .getWidth () != graphicsImage .getWidth () ||
338+ offscreen .getHeight () != graphicsImage .getHeight ()) {
339+ System .out .println ("creating new image" );
340+ offscreen = (BufferedImage )
341+ canvas .createImage (graphicsImage .getWidth (),
342+ graphicsImage .getHeight ());
343+ // off = offscreen.getGraphics();
344+ }
345+ // synchronized (offscreen) {
346+ Graphics2D off = (Graphics2D ) offscreen .getGraphics ();
347+ // off.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
348+ off .drawImage (graphicsImage , 0 , 0 , null );
349+ // }
350+ off .dispose ();
351+ synchronized (offscreenLock ) {
352+ BufferedImage temp = onscreen ;
353+ onscreen = offscreen ;
354+ offscreen = temp ;
355+ }
356+ canvas .repaint ();
274357 }
275- });
358+ }
276359 }
277360
278361
@@ -292,7 +375,7 @@ public Frame initOffscreen() {
292375 */
293376
294377 @ Override
295- public Canvas initCanvas (PApplet sketch ) {
378+ public Component initComponent (PApplet sketch ) {
296379 this .sketch = sketch ;
297380
298381 // needed for getPreferredSize() et al
@@ -727,39 +810,25 @@ public void setSmooth(int level) {
727810
728811 private boolean checkRetina () {
729812 if (PApplet .platform == PConstants .MACOSX ) {
730- // This should probably be reset each time there's a display change.
731- // A 5-minute search didn't turn up any such event in the Java API.
732- // Also, should we use the Toolkit associated with the editor window?
813+ // This should probably be reset each time there's a display change.
814+ // A 5-minute search didn't turn up any such event in the Java 7 API.
815+ // Also, should we use the Toolkit associated with the editor window?
733816 final String javaVendor = System .getProperty ("java.vendor" );
734- if (javaVendor .contains ("Apple" )) {
735- Float prop = (Float )
736- canvas .getToolkit ().getDesktopProperty ("apple.awt.contentScaleFactor" );
737- if (prop != null ) {
738- return prop == 2 ;
739- }
740- } else if (javaVendor .contains ("Oracle" )) {
741- String version = System .getProperty ("java.version" ); // 1.7.0_40
742- String [] m = PApplet .match (version , "1.(\\ d).*_(\\ d+)" );
743-
744- // Make sure this is Oracle Java 7u40 or later
745- if (m != null &&
746- PApplet .parseInt (m [1 ]) >= 7 &&
747- PApplet .parseInt (m [1 ]) >= 40 ) {
748- GraphicsEnvironment env = GraphicsEnvironment .getLocalGraphicsEnvironment ();
749- GraphicsDevice device = env .getDefaultScreenDevice ();
750-
751- try {
752- Field field = device .getClass ().getDeclaredField ("scale" );
753- if (field != null ) {
754- field .setAccessible (true );
755- Object scale = field .get (device );
756-
757- if (scale instanceof Integer && ((Integer )scale ).intValue () == 2 ) {
758- return true ;
759- }
817+ if (javaVendor .contains ("Oracle" )) {
818+ GraphicsEnvironment env = GraphicsEnvironment .getLocalGraphicsEnvironment ();
819+ GraphicsDevice device = env .getDefaultScreenDevice ();
820+
821+ try {
822+ Field field = device .getClass ().getDeclaredField ("scale" );
823+ if (field != null ) {
824+ field .setAccessible (true );
825+ Object scale = field .get (device );
826+
827+ if (scale instanceof Integer && ((Integer )scale ).intValue () == 2 ) {
828+ return true ;
760829 }
761- } catch ( Exception ignore ) { }
762- }
830+ }
831+ } catch ( Exception ignore ) { }
763832 }
764833 }
765834 return false ;
0 commit comments