8023098: XRender : AlphaComposite test results are incorrect.
authorceisserer
Tue, 22 Oct 2013 15:39:33 -0700
changeset 21234 e5d41ac9fb32
parent 21233 a36ed36d3209
child 21235 38393a2aaf88
8023098: XRender : AlphaComposite test results are incorrect. Reviewed-by: prr, bae
jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
jdk/src/solaris/classes/sun/java2d/xr/XRColor.java
jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java
jdk/src/solaris/classes/sun/java2d/xr/XRDrawImage.java
jdk/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java
jdk/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java
jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java
jdk/src/solaris/classes/sun/java2d/xr/XRUtils.java
--- a/jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java	Tue Oct 22 15:39:33 2013 -0700
@@ -76,8 +76,9 @@
     public void fillMask(XRSurfaceData dst) {
 
         boolean maskRequired = xrMgr.maskRequired();
+        boolean maskEvaluated = XRUtils.isMaskEvaluated(xrMgr.compRule);
 
-        if (maskRequired) {
+        if (maskRequired && maskEvaluated) {
             mainTile.calculateDirtyAreas();
             DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();
             mainTile.translate(-dirtyArea.x, -dirtyArea.y);
@@ -106,7 +107,15 @@
                 }
             }
         } else {
-            xrMgr.XRRenderRectangles(dst, mainTile.getRects());
+            /*
+             * If a mask would be required to store geometry (maskRequired)
+             * composition has to be done rectangle-by-rectagle.
+             */
+            if(xrMgr.isSolidPaintActive()) {
+                xrMgr.XRRenderRectangles(dst, mainTile.getRects());
+            } else {
+                xrMgr.XRCompositeRectangles(dst, mainTile.getRects());
+            }
         }
 
         mainTile.reset();
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRColor.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRColor.java	Tue Oct 22 15:39:33 2013 -0700
@@ -54,6 +54,7 @@
     }
 
     public XRColor(Color color) {
+        setColorValues(color);
     }
 
     public void setColorValues(Color color) {
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java	Tue Oct 22 15:39:33 2013 -0700
@@ -48,7 +48,12 @@
     private static boolean enableGradCache = true;
     private static XRCompositeManager instance;
 
-    XRSurfaceData src;
+    private final static int SOLID = 0;
+    private final static int TEXTURE = 1;
+    private final static int GRADIENT = 2;
+
+    int srcType;
+    XRSolidSrcPict solidSrc32;
     XRSurfaceData texture;
     XRSurfaceData gradient;
     int alphaMask = XRUtils.None;
@@ -84,7 +89,6 @@
 
     private XRCompositeManager(XRSurfaceData surface) {
         con = new XRBackendNative();
-        // con = XRBackendJava.getInstance();
 
         String gradProp =
             AccessController.doPrivileged(new PrivilegedAction<String>() {
@@ -109,14 +113,7 @@
     public void initResources(XRSurfaceData surface) {
         int parentXid = surface.getXid();
 
-        int solidPixmap = con.createPixmap(parentXid, 32, 1, 1);
-        int solidSrcPictXID = con.createPicture(solidPixmap,
-                XRUtils.PictStandardARGB32);
-        con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
-        con.renderRectangle(solidSrcPictXID, XRUtils.PictOpSrc,
-                XRColor.FULL_ALPHA, 0, 0, 1, 1);
-        solidSrcPict = new XRSurfaceData.XRInternalSurfaceData(con,
-                solidSrcPictXID);
+        solidSrc32 = new XRSolidSrcPict(con, parentXid);
         setForeground(0);
 
         int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1);
@@ -135,9 +132,7 @@
     }
 
     public void setForeground(int pixel) {
-        solidColor.setColorValues(pixel, false);
-        con.renderRectangle(solidSrcPict.picture, XRUtils.PictOpSrc,
-                solidColor, 0, 0, 1, 1);
+        solidColor.setColorValues(pixel, true);
     }
 
     public void setGradientPaint(XRSurfaceData gradient) {
@@ -145,16 +140,16 @@
             con.freePicture(this.gradient.picture);
         }
         this.gradient = gradient;
-        src = gradient;
+        srcType = GRADIENT;
     }
 
     public void setTexturePaint(XRSurfaceData texture) {
         this.texture = texture;
-        src = texture;
+        this.srcType = TEXTURE;
     }
 
     public void XRResetPaint() {
-        src = solidSrcPict;
+        srcType = SOLID;
     }
 
     public void validateCompositeState(Composite comp, AffineTransform xform,
@@ -175,7 +170,7 @@
             validatedComp = comp;
         }
 
-        if (sg2d != null && validatedPixel != sg2d.pixel) {
+        if (sg2d != null && (validatedPixel != sg2d.pixel  || updatePaint)) {
             validatedPixel = sg2d.pixel;
             setForeground(validatedPixel);
         }
@@ -191,14 +186,14 @@
             validatedPaint = paint;
         }
 
-        if (src != solidSrcPict) {
+        if (srcType != SOLID) {
             AffineTransform at = (AffineTransform) xform.clone();
             try {
                 at.invert();
             } catch (NoninvertibleTransformException e) {
                 at.setToIdentity();
             }
-            src.validateAsSource(at, -1, XRUtils.ATransOpToXRQuality(sg2d.interpolationType));
+            getCurrentSource().validateAsSource(at, -1, XRUtils.ATransOpToXRQuality(sg2d.interpolationType));
         }
     }
 
@@ -234,13 +229,13 @@
 
     public boolean maskRequired() {
         return (!xorEnabled)
-                && ((src != solidSrcPict)
-                        || (src == solidSrcPict && solidColor.alpha != 0xffff) || (extraAlpha != 1.0f));
+                && ((srcType != SOLID)
+                        || (srcType == SOLID && (solidColor.alpha != 0xffff) || (extraAlpha != 1.0f)));
     }
 
     public void XRComposite(int src, int mask, int dst, int srcX, int srcY,
             int maskX, int maskY, int dstX, int dstY, int width, int height) {
-        int cachedSrc = (src == XRUtils.None) ? this.src.picture : src;
+        int cachedSrc = (src == XRUtils.None) ? getCurrentSource().picture : src;
         int cachedX = srcX;
         int cachedY = srcY;
 
@@ -276,7 +271,7 @@
         renderReferenceY = (int) Math.floor(XRUtils
                 .XFixedToDouble(renderReferenceY));
 
-        con.renderCompositeTrapezoids(compRule, src.picture,
+        con.renderCompositeTrapezoids(compRule, getCurrentSource().picture,
                 XRUtils.PictStandardA8, dst, renderReferenceX,
                 renderReferenceY, trapList);
     }
@@ -294,15 +289,46 @@
         }
     }
 
+    public void XRCompositeRectangles(XRSurfaceData dst, GrowableRectArray rects) {
+        int srcPict = getCurrentSource().picture;
+
+        for(int i=0; i < rects.getSize(); i++) {
+            int x = rects.getX(i);
+            int y = rects.getY(i);
+            int width = rects.getWidth(i);
+            int height = rects.getHeight(i);
+
+            con.renderComposite(compRule, srcPict, XRUtils.None, dst.picture, x, y, 0, 0, x, y, width, height);
+        }
+    }
+
+    protected XRSurfaceData getCurrentSource() {
+        switch(srcType) {
+        case SOLID:
+            return solidSrc32.prepareSrcPict(validatedPixel);
+        case TEXTURE:
+            return texture;
+        case GRADIENT:
+            return gradient;
+        }
+
+        return null;
+    }
+
     public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx,
             int sy, int dx, int dy, int w, int h) {
         con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx,
                 sy, 0, 0, dx, dy, w, h);
     }
 
-    public void compositeText(XRSurfaceData dst, int sx, int sy,
-            int glyphSet, int maskFormat, GrowableEltArray elts) {
-        con.XRenderCompositeText(compRule, src.picture, dst.picture,
+    public void compositeText(XRSurfaceData dst, int sx, int sy, int glyphSet,
+            int maskFormat, GrowableEltArray elts) {
+        /*
+         * Try to emulate the SRC blend mode with SRC_OVER.
+         * We bail out during pipe validation for cases where this is not possible.
+         */
+        byte textCompRule = (compRule != XRUtils.PictOpSrc) ? compRule : XRUtils.PictOpOver;
+        con.XRenderCompositeText(textCompRule, getCurrentSource().picture, dst.picture,
                 maskFormat, sx, sy, 0, 0, glyphSet, elts);
     }
 
@@ -315,7 +341,11 @@
     }
 
     public boolean isTexturePaintActive() {
-        return src == texture;
+        return srcType == TEXTURE;
+    }
+
+    public boolean isSolidPaintActive() {
+        return srcType == SOLID;
     }
 
     public XRColor getAlphaColor() {
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRDrawImage.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRDrawImage.java	Tue Oct 22 15:39:33 2013 -0700
@@ -38,6 +38,7 @@
  */
 
 public class XRDrawImage extends DrawImage {
+
     @Override
     protected void renderImageXform(SunGraphics2D sg, Image img,
             AffineTransform tx, int interpType, int sx1, int sy1, int sx2,
@@ -45,20 +46,24 @@
         SurfaceData dstData = sg.surfaceData;
         SurfaceData srcData = dstData.getSourceSurfaceData(img,
                 SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, bgColor);
+        int compRule = ((AlphaComposite) sg.composite).getRule();
+        float extraAlpha = ((AlphaComposite) sg.composite).getAlpha();
 
         if (srcData != null && !isBgOperation(srcData, bgColor)
-                && interpType <= AffineTransformOp.TYPE_BILINEAR) {
+                && interpType <= AffineTransformOp.TYPE_BILINEAR
+                && (XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule))
+                        || (XRUtils.isTransformQuadrantRotated(tx)) && extraAlpha == 1.0f))
+                         {
             SurfaceType srcType = srcData.getSurfaceType();
             SurfaceType dstType = dstData.getSurfaceType();
 
             TransformBlit blit = TransformBlit.getFromCache(srcType,
                     sg.imageComp, dstType);
-
             if (blit != null) {
                 blit.Transform(srcData, dstData, sg.composite,
                         sg.getCompClip(), tx, interpType, sx1, sy1, 0, 0, sx2
                                 - sx1, sy2 - sy1);
-                return;
+                    return;
             }
         }
 
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java	Tue Oct 22 15:39:33 2013 -0700
@@ -84,7 +84,7 @@
 
             int maskPict = maskBuffer.getMaskBuffer().
                          uploadMask(width, height, maskscan, maskoff, mask);
-            maskBuffer.XRComposite(x11sd.getPicture(), maskPict, x11sd.picture,
+            maskBuffer.XRComposite(x11sd.getPicture(), maskPict, x11dst.getPicture(),
                                   srcx, srcy, 0, 0, dstx, dsty, width, height);
             maskBuffer.getMaskBuffer().clearUploadMask(maskPict, width, height);
         } finally {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java	Tue Oct 22 15:39:33 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.java2d.xr;
+
+public class XRSolidSrcPict {
+    XRBackend con;
+
+    XRSurfaceData srcPict;
+    XRColor xrCol;
+    int curPixVal = -1;
+
+    public XRSolidSrcPict(XRBackend con, int parentXid) {
+        this.con = con;
+
+        xrCol = new XRColor();
+        int solidPixmap = con.createPixmap(parentXid, 32, 1, 1);
+        int solidSrcPictXID = con.createPicture(solidPixmap, XRUtils.PictStandardARGB32);
+        con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
+        con.renderRectangle(solidSrcPictXID, XRUtils.PictOpSrc, XRColor.FULL_ALPHA, 0, 0, 1, 1);
+        srcPict = new XRSurfaceData.XRInternalSurfaceData(con, solidSrcPictXID);
+    }
+
+    public XRSurfaceData prepareSrcPict(int pixelVal) {
+        if(pixelVal != curPixVal) {
+            xrCol.setColorValues(pixelVal, false);
+            con.renderRectangle(srcPict.picture, XRUtils.PictOpSrc, xrCol, 0, 0, 1, 1);
+            this.curPixVal = pixelVal;
+        }
+
+        return srcPict;
+    }
+
+}
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java	Tue Oct 22 15:39:33 2013 -0700
@@ -109,6 +109,7 @@
         return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig);
     }
 
+    @Override
     public void validatePipe(SunGraphics2D sg2d) {
         TextPipe textpipe;
         boolean validated = false;
@@ -117,14 +118,8 @@
          * The textpipe for now can't handle TexturePaint when extra-alpha is
          * specified nore XOR mode
          */
-        if (sg2d.compositeState < SunGraphics2D.COMP_XOR &&
-            (sg2d.paintState < SunGraphics2D.PAINT_TEXTURE ||
-             sg2d.composite == null ||
-             !(sg2d.composite instanceof AlphaComposite) ||
-             ((AlphaComposite) sg2d.composite).getAlpha() == 1.0f))
+        if ((textpipe = getTextPipe(sg2d)) == null)
         {
-            textpipe = xrtextpipe;
-        } else {
             super.validatePipe(sg2d);
             textpipe = sg2d.textpipe;
             validated = true;
@@ -184,13 +179,38 @@
         sg2d.imagepipe = xrDrawImage;
     }
 
+    protected TextPipe getTextPipe(SunGraphics2D sg2d) {
+        boolean supportedPaint = sg2d.compositeState <= SunGraphics2D.COMP_ALPHA
+                && (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR || sg2d.composite == null);
+
+        boolean supportedCompOp = false;
+        if (sg2d.composite instanceof AlphaComposite) {
+            int compRule = ((AlphaComposite) sg2d.composite).getRule();
+            supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule))
+                    || (compRule == AlphaComposite.SRC
+                                && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR);
+        }
+
+        return (supportedPaint && supportedCompOp) ? xrtextpipe : null;
+    }
+
     protected MaskFill getMaskFill(SunGraphics2D sg2d) {
-        if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR &&
-            !XRPaints.isValid(sg2d))
-        {
-            return null;
+        AlphaComposite aComp = null;
+        if(sg2d.composite != null
+                && sg2d.composite instanceof AlphaComposite) {
+            aComp = (AlphaComposite) sg2d.composite;
         }
-        return super.getMaskFill(sg2d);
+
+        boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR
+                || XRPaints.isValid(sg2d);
+
+        boolean supportedCompOp = false;
+        if(aComp != null) {
+            int rule = aComp.getRule();
+            supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(rule));
+        }
+
+        return (supportedPaint && supportedCompOp) ?  super.getMaskFill(sg2d) : null;
     }
 
     public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRUtils.java	Tue Oct 22 13:47:45 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRUtils.java	Tue Oct 22 15:39:33 2013 -0700
@@ -27,6 +27,7 @@
 
 import java.awt.*;
 import java.awt.MultipleGradientPaint.*;
+import java.awt.geom.AffineTransform;
 import java.awt.image.*;
 import sun.java2d.loops.*;
 import static java.awt.AlphaComposite.*;
@@ -258,4 +259,21 @@
     public static int clampToUShort(int x) {
         return (x > 65535 ? 65535 : (x < 0) ? 0 : x);
     }
+
+    public static boolean isTransformQuadrantRotated(AffineTransform tr) {
+        return ((tr.getType() & (AffineTransform.TYPE_GENERAL_ROTATION |
+                 AffineTransform.TYPE_GENERAL_TRANSFORM)) == 0);
+    }
+
+    public static boolean isMaskEvaluated(byte xrCompRule) {
+        switch (xrCompRule) {
+        case PictOpOver:
+        case PictOpOverReverse:
+        case PictOpAtop:
+        case PictOpXor:
+            return true;
+        }
+
+        return false;
+    }
 }