From 84e5f9ded35cadee781a272cfc8ef3ef29cfe18c Mon Sep 17 00:00:00 2001 From: ceisserer Date: Tue, 22 Oct 2013 15:39:33 -0700 Subject: [PATCH] 8023098: XRender : AlphaComposite test results are incorrect. Reviewed-by: prr, bae --- .../sun/java2d/xr/MaskTileManager.java | 13 ++- .../classes/sun/java2d/xr/XRColor.java | 1 + .../sun/java2d/xr/XRCompositeManager.java | 84 +++++++++++++------ .../classes/sun/java2d/xr/XRDrawImage.java | 11 ++- .../classes/sun/java2d/xr/XRMaskBlit.java | 2 +- .../classes/sun/java2d/xr/XRSolidSrcPict.java | 57 +++++++++++++ .../classes/sun/java2d/xr/XRSurfaceData.java | 44 +++++++--- .../classes/sun/java2d/xr/XRUtils.java | 18 ++++ 8 files changed, 185 insertions(+), 45 deletions(-) create mode 100644 src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java diff --git a/src/solaris/classes/sun/java2d/xr/MaskTileManager.java b/src/solaris/classes/sun/java2d/xr/MaskTileManager.java index 9b2be2744..728e868bf 100644 --- a/src/solaris/classes/sun/java2d/xr/MaskTileManager.java +++ b/src/solaris/classes/sun/java2d/xr/MaskTileManager.java @@ -76,8 +76,9 @@ public class MaskTileManager { 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 @@ public class MaskTileManager { } } } 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(); diff --git a/src/solaris/classes/sun/java2d/xr/XRColor.java b/src/solaris/classes/sun/java2d/xr/XRColor.java index d1c3f6b71..973255552 100644 --- a/src/solaris/classes/sun/java2d/xr/XRColor.java +++ b/src/solaris/classes/sun/java2d/xr/XRColor.java @@ -54,6 +54,7 @@ public class XRColor { } public XRColor(Color color) { + setColorValues(color); } public void setColorValues(Color color) { diff --git a/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java index 9d005b176..f9c06268d 100644 --- a/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java +++ b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java @@ -48,7 +48,12 @@ public class XRCompositeManager { 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 @@ public class XRCompositeManager { private XRCompositeManager(XRSurfaceData surface) { con = new XRBackendNative(); - // con = XRBackendJava.getInstance(); String gradProp = AccessController.doPrivileged(new PrivilegedAction() { @@ -109,14 +113,7 @@ public class XRCompositeManager { 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 class XRCompositeManager { } 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 @@ public class XRCompositeManager { 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 @@ public class XRCompositeManager { validatedComp = comp; } - if (sg2d != null && validatedPixel != sg2d.pixel) { + if (sg2d != null && (validatedPixel != sg2d.pixel || updatePaint)) { validatedPixel = sg2d.pixel; setForeground(validatedPixel); } @@ -191,14 +186,14 @@ public class XRCompositeManager { 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 class XRCompositeManager { 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 @@ public class XRCompositeManager { 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 class XRCompositeManager { } } + 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 class XRCompositeManager { } public boolean isTexturePaintActive() { - return src == texture; + return srcType == TEXTURE; + } + + public boolean isSolidPaintActive() { + return srcType == SOLID; } public XRColor getAlphaColor() { diff --git a/src/solaris/classes/sun/java2d/xr/XRDrawImage.java b/src/solaris/classes/sun/java2d/xr/XRDrawImage.java index 149edb79d..c5ecef462 100644 --- a/src/solaris/classes/sun/java2d/xr/XRDrawImage.java +++ b/src/solaris/classes/sun/java2d/xr/XRDrawImage.java @@ -38,6 +38,7 @@ import sun.java2d.pipe.*; */ 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 @@ public class XRDrawImage extends DrawImage { 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; } } diff --git a/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java b/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java index 978a3c4b9..7fd6046b7 100644 --- a/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java +++ b/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java @@ -84,7 +84,7 @@ public class XRMaskBlit extends MaskBlit { 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 { diff --git a/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java b/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java new file mode 100644 index 000000000..9d95769b8 --- /dev/null +++ b/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java @@ -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; + } + +} diff --git a/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java index 15b51267b..f05243e40 100644 --- a/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java +++ b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java @@ -109,6 +109,7 @@ public abstract class XRSurfaceData extends XSurfaceData { return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig); } + @Override public void validatePipe(SunGraphics2D sg2d) { TextPipe textpipe; boolean validated = false; @@ -117,14 +118,8 @@ public abstract class XRSurfaceData extends XSurfaceData { * 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 @@ public abstract class XRSurfaceData extends XSurfaceData { 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; + } + + 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 super.getMaskFill(sg2d); + + return (supportedPaint && supportedCompOp) ? super.getMaskFill(sg2d) : null; } public RenderLoops getRenderLoops(SunGraphics2D sg2d) { diff --git a/src/solaris/classes/sun/java2d/xr/XRUtils.java b/src/solaris/classes/sun/java2d/xr/XRUtils.java index 7a47999ff..0b0cecc37 100644 --- a/src/solaris/classes/sun/java2d/xr/XRUtils.java +++ b/src/solaris/classes/sun/java2d/xr/XRUtils.java @@ -27,6 +27,7 @@ package sun.java2d.xr; 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 class XRUtils { 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; + } } -- GitLab