8023098: XRender : AlphaComposite test results are incorrect.
Reviewed-by: prr, bae
--- 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;
+ }
}