diff --git a/core/src/processing/core/PGraphicsJava2D.java b/core/src/processing/core/PGraphicsJava2D.java index 9e28bc2b7..19f6bc1f6 100644 --- a/core/src/processing/core/PGraphicsJava2D.java +++ b/core/src/processing/core/PGraphicsJava2D.java @@ -59,6 +59,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { Canvas canvas; // boolean useCanvas = true; boolean useCanvas = false; +// boolean useRetina = true; +// boolean useOffscreen = true; // ~40fps + boolean useOffscreen = false; public Graphics2D g2; protected BufferedImage offscreen; @@ -154,6 +157,8 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { // parent.setLayout(new BorderLayout()); // parent.add(canvas, BorderLayout.CENTER); parent.add(canvas); +// canvas.validate(); +// parent.doLayout(); if (canvas.getWidth() != width || canvas.getHeight() != height) { PApplet.debug("PGraphicsJava2D comp size being set to " + width + "x" + height); @@ -171,14 +176,31 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { // using a compatible image here doesn't seem to provide any performance boost - // Needs to be RGB otherwise there's a major performance hit [0204] - // http://code.google.com/p/processing/issues/detail?id=729 - image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + if (useOffscreen) { + // Needs to be RGB otherwise there's a major performance hit [0204] + // http://code.google.com/p/processing/issues/detail?id=729 + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // GraphicsConfiguration gc = parent.getGraphicsConfiguration(); // image = gc.createCompatibleImage(width, height); - offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // offscreen = gc.createCompatibleImage(width, height); - g2 = (Graphics2D) offscreen.getGraphics(); + g2 = (Graphics2D) offscreen.getGraphics(); + + } else { +// System.out.println("hopefully faster " + width + " " + height); +// new Exception().printStackTrace(System.out); + + GraphicsConfiguration gc = parent.getGraphicsConfiguration(); + // If not realized (off-screen, i.e the Color Selector Tool), + // gc will be null. + if (gc == null) { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + gc = ge.getDefaultScreenDevice().getDefaultConfiguration(); + } + + image = gc.createCompatibleImage(width, height); + g2 = (Graphics2D) image.getGraphics(); + } } } else { // Since this buffer's offscreen anyway, no need for the extra offscreen @@ -187,9 +209,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); g2 = (Graphics2D) image.getGraphics(); } - if (!useCanvas) { - defaultComposite = g2.getComposite(); - } +// if (!useCanvas) { +// defaultComposite = g2.getComposite(); +// } // can't un-set this because this may be only a resize // http://dev.processing.org/bugs/show_bug.cgi?id=463 @@ -226,6 +248,21 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { @Override public void beginDraw() { + if (primarySurface && !useOffscreen) { + GraphicsConfiguration gc = parent.getGraphicsConfiguration(); + if (false) { + if (image == null || ((VolatileImage) image).validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) { + image = gc.createCompatibleVolatileImage(width, height); + } + } else { + if (image == null) { + image = gc.createCompatibleImage(width, height); + //System.out.println("image type is " + image); + } + } + g2 = (Graphics2D) image.getGraphics(); + } + if (useCanvas && primarySurface) { if (parent.frameCount == 0) { canvas.createBufferStrategy(2); @@ -275,9 +312,12 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { // alternate version //canvas.repaint(); // ?? what to do for swapping buffers +// System.out.println("endDraw() frameCount is " + parent.frameCount); +// if (parent.frameCount != 0) { redraw(); +// } - } else { + } else if (useOffscreen) { // don't copy the pixels/data elements of the buffered image directly, // since it'll disable the nice speedy pipeline stuff, sending all drawing // into a world of suck that's rough 6 trillion times slower. @@ -285,6 +325,10 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { //System.out.println("inside j2d sync"); image.getGraphics().drawImage(offscreen, 0, 0, null); } + + } else { + g2.dispose(); +// System.out.println("not doing anything special in endDraw()"); } } else { // TODO this is probably overkill for most tasks... @@ -353,7 +397,13 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { //protected void checkSettings() - //protected void defaultSettings() + @Override + protected void defaultSettings() { + if (!useCanvas) { + defaultComposite = g2.getComposite(); + } + super.defaultSettings(); + } //protected void reapplySettings() @@ -2056,20 +2106,25 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { int[] clearPixels; protected void clearPixels(int color) { + // On a hi-res display, image may be larger than width/height + int imageWidth = image.getWidth(null); + int imageHeight = image.getHeight(null); + // Create a small array that can be used to set the pixels several times. // Using a single-pixel line of length 'width' is a tradeoff between // speed (setting each pixel individually is too slow) and memory // (an array for width*height would waste lots of memory if it stayed // resident, and would terrify the gc if it were re-created on each trip // to background(). - WritableRaster raster = ((BufferedImage) image).getRaster(); +// WritableRaster raster = ((BufferedImage) image).getRaster(); // WritableRaster raster = image.getRaster(); - if ((clearPixels == null) || (clearPixels.length < width)) { - clearPixels = new int[width]; + WritableRaster raster = getRaster(); + if ((clearPixels == null) || (clearPixels.length < imageWidth)) { + clearPixels = new int[imageWidth]; } - Arrays.fill(clearPixels, backgroundColor); - for (int i = 0; i < height; i++) { - raster.setDataElements(0, i, width, 1, clearPixels); + Arrays.fill(clearPixels, 0, imageWidth, backgroundColor); + for (int i = 0; i < imageHeight; i++) { + raster.setDataElements(0, i, imageWidth, 1, clearPixels); } } @@ -2101,7 +2156,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { pushMatrix(); resetMatrix(); g2.setColor(bgColor); //, backgroundAlpha)); - g2.fillRect(0, 0, width, height); +// g2.fillRect(0, 0, width, height); + // On a hi-res display, image may be larger than width/height + g2.fillRect(0, 0, image.getWidth(null), image.getHeight(null)); popMatrix(); g2.setComposite(oldComposite); @@ -2200,15 +2257,31 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { // getImage, setCache, getCache, removeCache, isModified, setModified + protected WritableRaster getRaster() { + if (primarySurface) { + // 'offscreen' will probably be removed in the next release + if (useOffscreen) { + return ((BufferedImage) offscreen).getRaster(); + } + // when possible, we'll try VolatileImage + if (image instanceof VolatileImage) { + return ((VolatileImage) image).getSnapshot().getRaster(); + } + } + return ((BufferedImage) image).getRaster(); + //((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); + } + + @Override public void loadPixels() { if ((pixels == null) || (pixels.length != width * height)) { pixels = new int[width * height]; } //((BufferedImage) image).getRGB(0, 0, width, height, pixels, 0, width); - WritableRaster raster = ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); +// WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); // WritableRaster raster = image.getRaster(); - raster.getDataElements(0, 0, width, height, pixels); + getRaster().getDataElements(0, 0, width, height, pixels); } @@ -2221,9 +2294,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { @Override public void updatePixels() { //updatePixels(0, 0, width, height); - WritableRaster raster = ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); +// WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); // WritableRaster raster = image.getRaster(); - raster.setDataElements(0, 0, width, height, pixels); + getRaster().setDataElements(0, 0, width, height, pixels); } @@ -2255,9 +2328,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { public int get(int x, int y) { if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0; //return ((BufferedImage) image).getRGB(x, y); - WritableRaster raster = ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); +// WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); // WritableRaster raster = image.getRaster(); - raster.getDataElements(x, y, getset); + getRaster().getDataElements(x, y, getset); return getset[0]; } @@ -2272,8 +2345,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { PImage target, int targetX, int targetY) { // last parameter to getRGB() is the scan size of the *target* buffer //((BufferedImage) image).getRGB(x, y, w, h, output.pixels, 0, w); - WritableRaster raster = - ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); +// WritableRaster raster = +// ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); + WritableRaster raster = getRaster(); if (sourceWidth == target.width && sourceHeight == target.height) { raster.getDataElements(sourceX, sourceY, sourceWidth, sourceHeight, target.pixels); @@ -2306,9 +2380,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return; // ((BufferedImage) image).setRGB(x, y, argb); getset[0] = argb; - WritableRaster raster = ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); +// WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); // WritableRaster raster = image.getRaster(); - raster.setDataElements(x, y, getset); + getRaster().setDataElements(x, y, getset); } @@ -2320,8 +2394,8 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { int sourceX, int sourceY, int sourceWidth, int sourceHeight, int targetX, int targetY) { - WritableRaster raster = - ((BufferedImage) (primarySurface ? offscreen : image)).getRaster(); + WritableRaster raster = getRaster(); +// ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster(); if ((sourceX == 0) && (sourceY == 0) && (sourceWidth == sourceImage.width) && @@ -2380,8 +2454,6 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ { public void copy(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) { if ((sw != dw) || (sh != dh)) { -// Image img = primarySurface ? offscreen : image; -// g2.drawImage(img, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, null); g2.drawImage(image, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, null); } else { diff --git a/core/src/processing/core/PGraphicsRetina2D.java b/core/src/processing/core/PGraphicsRetina2D.java new file mode 100644 index 000000000..0a4c0c7a9 --- /dev/null +++ b/core/src/processing/core/PGraphicsRetina2D.java @@ -0,0 +1,318 @@ +package processing.core; + +import java.awt.*; +import java.awt.image.*; + + +public class PGraphicsRetina2D extends PGraphicsJava2D { + + + ////////////////////////////////////////////////////////////// + + // INTERNAL + + + public PGraphicsRetina2D() { } + + + @Override + protected void allocate() { +// parent.setIgnoreRepaint(true); +// g2 = (Graphics2D) parent.getGraphics(); + + + /* + if (primarySurface) { + if (useCanvas) { + if (canvas != null) { + parent.removeListeners(canvas); + parent.remove(canvas); + } + canvas = new Canvas(); + canvas.setIgnoreRepaint(true); + +// parent.setLayout(new BorderLayout()); +// parent.add(canvas, BorderLayout.CENTER); + parent.add(canvas); + + if (canvas.getWidth() != width || canvas.getHeight() != height) { + PApplet.debug("PGraphicsJava2D comp size being set to " + width + "x" + height); + canvas.setSize(width, height); + } else { + PApplet.debug("PGraphicsJava2D comp size already " + width + "x" + height); + } + + parent.addListeners(canvas); +// canvas.createBufferStrategy(1); +// g2 = (Graphics2D) canvas.getGraphics(); + + } else { + parent.updateListeners(parent); // in case they're already there + + // using a compatible image here doesn't seem to provide any performance boost + + // Needs to be RGB otherwise there's a major performance hit [0204] + // http://code.google.com/p/processing/issues/detail?id=729 + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// GraphicsConfiguration gc = parent.getGraphicsConfiguration(); +// image = gc.createCompatibleImage(width, height); + offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); +// offscreen = gc.createCompatibleImage(width, height); + g2 = (Graphics2D) offscreen.getGraphics(); + } + } else { + // Since this buffer's offscreen anyway, no need for the extra offscreen + // buffer. However, unlike the primary surface, this feller needs to be + // ARGB so that blending ("alpha" compositing) will work properly. + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + g2 = (Graphics2D) image.getGraphics(); + } + */ + } + + + ////////////////////////////////////////////////////////////// + + // FRAME + + @Override + public void beginDraw() { +// g2 = (Graphics2D) parent.getGraphics(); + + GraphicsConfiguration gc = parent.getGraphicsConfiguration(); + if (false) { + if (image == null || ((VolatileImage) image).validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) { + image = gc.createCompatibleVolatileImage(width*2, height*2); + } + } else { + if (image == null) { + image = gc.createCompatibleImage(width*2, height*2); +// System.out.println("image type is " + image); + } + } + g2 = (Graphics2D) image.getGraphics(); +// g2.scale(2, 2); + +// if (bimage == null || +// bimage.getWidth() != width || +// bimage.getHeight() != height) { +// PApplet.debug("PGraphicsJava2D creating new image"); +// bimage = gc.createCompatibleImage(width, height); + + checkSettings(); + resetMatrix(); // reset model matrix + + // inserted here for retina + g2.scale(2, 2); + + vertexCount = 0; + } + + + @Override + public void endDraw() { + g2.dispose(); + /* + // hm, mark pixels as changed, because this will instantly do a full + // copy of all the pixels to the surface.. so that's kind of a mess. + //updatePixels(); + + if (primarySurface) { + //if (canvas != null) { + if (useCanvas) { + //System.out.println(canvas); + + // alternate version + //canvas.repaint(); // ?? what to do for swapping buffers + + redraw(); + + } else { + // don't copy the pixels/data elements of the buffered image directly, + // since it'll disable the nice speedy pipeline stuff, sending all drawing + // into a world of suck that's rough 6 trillion times slower. + synchronized (image) { + //System.out.println("inside j2d sync"); + image.getGraphics().drawImage(offscreen, 0, 0, null); + } + } + } else { + // TODO this is probably overkill for most tasks... + loadPixels(); + } + + // Marking as modified, and then calling updatePixels() in + // the super class, which just sets the mx1, my1, mx2, my2 + // coordinates of the modified area. This avoids doing the + // full copy of the pixels to the surface in this.updatePixels(). + setModified(); + super.updatePixels(); + */ + } + + + + ////////////////////////////////////////////////////////////// + + // BACKGROUND + + +// @Override +// public void backgroundImpl() { +// if (backgroundAlpha) { +// clearPixels(backgroundColor); +// +// } else { +// Color bgColor = new Color(backgroundColor); +// // seems to fire an additional event that causes flickering, +// // like an extra background erase on OS X +//// if (canvas != null) { +//// canvas.setBackground(bgColor); +//// } +// //new Exception().printStackTrace(System.out); +// // in case people do transformations before background(), +// // need to handle this with a push/reset/pop +// Composite oldComposite = g2.getComposite(); +// g2.setComposite(defaultComposite); +// +// pushMatrix(); +// resetMatrix(); +// g2.setColor(bgColor); //, backgroundAlpha)); +// g2.fillRect(0, 0, width, height); +// popMatrix(); +// +// g2.setComposite(oldComposite); +// } +// } + + + + ////////////////////////////////////////////////////////////// + + + /* + @Override + public void loadPixels() { + nope("loadPixels"); + } + + @Override + public void updatePixels() { + nope("updatePixels"); + } + + @Override + public void updatePixels(int x, int y, int c, int d) { + nope("updatePixels"); + } + + // + + @Override + public int get(int x, int y) { + nope("get"); + return 0; // not reached + } + + @Override + public PImage get(int x, int y, int c, int d) { + nope("get"); + return null; // not reached + } + + @Override + public PImage get() { + nope("get"); + return null; // not reached + } + + @Override + public void set(int x, int y, int argb) { + nope("set"); + } + + @Override + public void set(int x, int y, PImage image) { + nope("set"); + } + + // + + @Override + public void mask(int alpha[]) { + nope("mask"); + } + + @Override + public void mask(PImage alpha) { + nope("mask"); + } + + // + + @Override + public void filter(int kind) { + nope("filter"); + } + + @Override + public void filter(int kind, float param) { + nope("filter"); + } + + // + + @Override + public void copy(int sx1, int sy1, int sx2, int sy2, + int dx1, int dy1, int dx2, int dy2) { + nope("copy"); + } + + @Override + public void copy(PImage src, + int sx1, int sy1, int sx2, int sy2, + int dx1, int dy1, int dx2, int dy2) { + nope("copy"); + } + + // + + public void blend(int sx, int sy, int dx, int dy, int mode) { + nope("blend"); + } + + public void blend(PImage src, + int sx, int sy, int dx, int dy, int mode) { + nope("blend"); + } + + @Override + public void blend(int sx1, int sy1, int sx2, int sy2, + int dx1, int dy1, int dx2, int dy2, int mode) { + nope("blend"); + } + + @Override + public void blend(PImage src, + int sx1, int sy1, int sx2, int sy2, + int dx1, int dy1, int dx2, int dy2, int mode) { + nope("blend"); + } + + // + + @Override + public boolean save(String filename) { + nope("save"); + return false; + } + */ + + + ////////////////////////////////////////////////////////////// + + + protected void nope(String function) { + throw new RuntimeException("No " + function + "() for PGraphicsRetina2D"); + } +} \ No newline at end of file diff --git a/core/todo.txt b/core/todo.txt index 4334263fc..640390116 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -39,6 +39,8 @@ A P3D sketches failing to run A http://code.google.com/p/processing/issues/detail?id=1500 A transparent pixels are not set on multisampled offscreen GL surfaces A http://code.google.com/p/processing/issues/detail?id=1516 +A clean-up PShape API +A http://code.google.com/p/processing/issues/detail?id=1518 cleaning/earlier C textureWrap() CLAMP and REPEAT now added @@ -114,6 +116,8 @@ _ JSONObject.has(key) vs XML.hasAttribute(attr) vs HashMap.containsKey() _ and how it should be handled with hash/dict _ right now using hasKey().. in JSONObject +_ add randomGaussian() + _ OpenGL/P3D sketches show graphical corruption _ http://code.google.com/p/processing/issues/detail?id=1452 diff --git a/todo.txt b/todo.txt index 28919c890..404fcacc0 100644 --- a/todo.txt +++ b/todo.txt @@ -41,6 +41,8 @@ o do command line to run through all examples? X remove Quaqua X http://code.google.com/p/processing/issues/detail?id=1509 X remove separate launch of QT movie creator +X Don't open Changes page on the Wiki from command line +X http://code.google.com/p/processing/issues/detail?id=1520 manindra M bug that was causing the Debugger to point to wrong break point line numbers