--- a/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java Wed Jun 11 10:53:27 2014 +0400
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java Wed Jun 11 14:21:12 2014 +0400
@@ -510,6 +510,7 @@
final class OGLSurfaceToSwBlit extends Blit {
private final int typeval;
+ private WeakReference<SurfaceData> srcTmp;
// destination will actually be ArgbPre or Argb
OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval) {
@@ -519,11 +520,66 @@
this.typeval = typeval;
}
+ private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
+ Composite comp, Region clip,
+ int sx, int sy, int dx, int dy,
+ int w, int h) {
+ SurfaceData cachedSrc = null;
+ if (srcTmp != null) {
+ // use cached intermediate surface, if available
+ cachedSrc = srcTmp.get();
+ }
+
+ // We can convert argb_pre data from OpenGL surface in two places:
+ // - During OpenGL surface -> SW blit
+ // - During SW -> SW blit
+ // The first one is faster when we use opaque OGL surface, because in
+ // this case we simply skip conversion and use color components as is.
+ // Because of this we align intermediate buffer type with type of
+ // destination not source.
+ final int type = typeval == OGLSurfaceData.PF_INT_ARGB_PRE ?
+ BufferedImage.TYPE_INT_ARGB_PRE :
+ BufferedImage.TYPE_INT_ARGB;
+
+ src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
+
+ // copy intermediate SW to destination SW using complex clip
+ final Blit performop = Blit.getFromCache(src.getSurfaceType(),
+ CompositeType.SrcNoEa,
+ dst.getSurfaceType());
+ performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
+
+ if (src != cachedSrc) {
+ // cache the intermediate surface
+ srcTmp = new WeakReference<>(src);
+ }
+ }
+
public void Blit(SurfaceData src, SurfaceData dst,
Composite comp, Region clip,
int sx, int sy, int dx, int dy,
int w, int h)
{
+ if (clip != null) {
+ clip = clip.getIntersectionXYWH(dx, dy, w, h);
+ // At the end this method will flush the RenderQueue, we should exit
+ // from it as soon as possible.
+ if (clip.isEmpty()) {
+ return;
+ }
+ sx += clip.getLoX() - dx;
+ sy += clip.getLoY() - dy;
+ dx = clip.getLoX();
+ dy = clip.getLoY();
+ w = clip.getWidth();
+ h = clip.getHeight();
+
+ if (!clip.isRectangular()) {
+ complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
+ return;
+ }
+ }
+
OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock();
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java Wed Jun 11 14:21:12 2014 +0400
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import static java.awt.geom.Rectangle2D.Double;
+
+/**
+ * @test
+ * @bug 8041644
+ * @summary Tests drawing volatile image to BI using different clip.
+ * Results of the blit compatibleImage to BI used for comparison.
+ * @author Sergey Bylokhov
+ * @run main/othervm -Dsun.java2d.d3d=false IncorrectClipSurface2SW
+ */
+public final class IncorrectClipSurface2SW {
+
+ private static int[] SCALES = {1, 2, 4};
+ private static int[] SIZES = {127, 3, 2, 1};
+ private static final Shape[] SHAPES = {new Rectangle(0, 0, 0, 0),
+ new Rectangle(0, 0, 1, 1),
+ new Rectangle(0, 1, 1, 1),
+ new Rectangle(1, 0, 1, 1),
+ new Rectangle(1, 1, 1, 1),
+
+ new Ellipse2D.Double(0, 0, 1, 1),
+ new Ellipse2D.Double(0, 1, 1, 1),
+ new Ellipse2D.Double(1, 0, 1, 1),
+ new Ellipse2D.Double(1, 1, 1, 1),
+ new Ellipse2D.Double(.25, .25, .5,
+ .5),
+
+ new Double(0, 0, 0.5, 0.5),
+ new Double(0, 0.5, 0.5, 0.5),
+ new Double(0.5, 0, 0.5, 0.5),
+ new Double(0.5, 0.5, 0.5, 0.5),
+ new Double(0.25, 0.25, 0.5, 0.5),
+ new Double(0, 0.25, 1, 0.5),
+ new Double(0.25, 0, 0.5, 1),
+
+ new Double(.10, .10, .20, .20),
+ new Double(.75, .75, .20, .20),
+ new Double(.75, .10, .20, .20),
+ new Double(.10, .75, .20, .20),};
+
+ public static void main(final String[] args) throws IOException {
+ GraphicsEnvironment ge = GraphicsEnvironment
+ .getLocalGraphicsEnvironment();
+ GraphicsConfiguration gc = ge.getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ AffineTransform at;
+ for (final int size : SIZES) {
+ for (final int scale : SCALES) {
+ final int sw = size * scale;
+ at = AffineTransform.getScaleInstance(sw, sw);
+ for (Shape clip : SHAPES) {
+ clip = at.createTransformedShape(clip);
+ for (Shape to : SHAPES) {
+ to = at.createTransformedShape(to);
+ // Prepare test images
+ VolatileImage vi = getVolatileImage(gc, size);
+ BufferedImage bi = getBufferedImage(sw);
+ // Prepare gold images
+ BufferedImage goldvi = getCompatibleImage(gc, size);
+ BufferedImage goldbi = getBufferedImage(sw);
+ draw(clip, to, vi, bi, scale);
+ draw(clip, to, goldvi, goldbi, scale);
+ validate(bi, goldbi);
+ }
+ }
+ }
+ }
+ }
+
+ private static void draw(Shape clip, Shape to, Image vi, BufferedImage bi,
+ int scale) {
+ Graphics2D big = bi.createGraphics();
+ big.setComposite(AlphaComposite.Src);
+ big.setClip(clip);
+ Rectangle toBounds = to.getBounds();
+ int x1 = toBounds.x;
+
+ int y1 = toBounds.y;
+ int x2 = x1 + toBounds.width;
+ int y2 = y1 + toBounds.height;
+ big.drawImage(vi, x1, y1, x2, y2, 0, 0, toBounds.width / scale,
+ toBounds.height / scale, null);
+ big.dispose();
+ vi.flush();
+ }
+
+ private static BufferedImage getBufferedImage(int sw) {
+ BufferedImage bi = new BufferedImage(sw, sw,
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2d = bi.createGraphics();
+ g2d.setColor(Color.RED);
+ g2d.fillRect(0, 0, sw, sw);
+ return bi;
+ }
+
+ private static VolatileImage getVolatileImage(GraphicsConfiguration gc,
+ int size) {
+ VolatileImage vi = gc.createCompatibleVolatileImage(size, size);
+ Graphics2D g2d = vi.createGraphics();
+ g2d.setColor(Color.GREEN);
+ g2d.fillRect(0, 0, size, size);
+ return vi;
+ }
+
+ private static BufferedImage getCompatibleImage(GraphicsConfiguration gc,
+ int size) {
+ BufferedImage image = gc.createCompatibleImage(size, size);
+ Graphics2D g2d = image.createGraphics();
+ g2d.setColor(Color.GREEN);
+ g2d.fillRect(0, 0, size, size);
+ return image;
+ }
+
+ private static void validate(BufferedImage bi, BufferedImage goldbi)
+ throws IOException {
+ for (int x = 0; x < bi.getWidth(); ++x) {
+ for (int y = 0; y < bi.getHeight(); ++y) {
+ if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) {
+ ImageIO.write(bi, "png", new File("actual.png"));
+ ImageIO.write(goldbi, "png", new File("expected.png"));
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ }
+ }
+}