1 /* 2 * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.java2d.xr; 27 28 import java.awt.*; 29 import java.awt.geom.*; 30 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 34 import sun.font.*; 35 import sun.java2d.*; 36 import sun.java2d.loops.*; 37 38 /** 39 * Manages per-application resources, e.g. the 1x1 pixmap used for solid color 40 * fill as well as per-application state e.g. the currently set source picture 41 * used for composition . 42 * 43 * @author Clemens Eisserer 44 */ 45 46 public class XRCompositeManager { 47 private static boolean enableGradCache = true; 48 private static XRCompositeManager instance; 49 50 private static final int SOLID = 0; 51 private static final int TEXTURE = 1; 52 private static final int GRADIENT = 2; 53 54 int srcType; 55 XRSolidSrcPict solidSrc32; 56 XRSurfaceData texture; 57 XRSurfaceData gradient; 58 int alphaMask = XRUtils.None; 59 60 XRColor solidColor = new XRColor(); 61 float extraAlpha = 1.0f; 62 byte compRule = XRUtils.PictOpOver; 63 XRColor alphaColor = new XRColor(); 64 65 XRSurfaceData solidSrcPict; 66 int alphaMaskPict; 67 int gradCachePixmap; 68 int gradCachePicture; 69 70 boolean xorEnabled = false; 71 int validatedPixel = 0; 72 Composite validatedComp; 73 Paint validatedPaint; 74 float validatedExtraAlpha = 1.0f; 75 76 XRBackend con; 77 MaskTileManager maskBuffer; 78 XRTextRenderer textRenderer; 79 XRMaskImage maskImage; 80 getInstance( XRSurfaceData surface)81 public static synchronized XRCompositeManager getInstance( 82 XRSurfaceData surface) { 83 if (instance == null) { 84 instance = new XRCompositeManager(surface); 85 } 86 return instance; 87 } 88 XRCompositeManager(XRSurfaceData surface)89 private XRCompositeManager(XRSurfaceData surface) { 90 con = new XRBackendNative(); 91 92 String gradProp = 93 AccessController.doPrivileged(new PrivilegedAction<String>() { 94 public String run() { 95 return System.getProperty("sun.java2d.xrgradcache"); 96 } 97 }); 98 99 enableGradCache = gradProp == null || 100 !(gradProp.equalsIgnoreCase("false") || 101 gradProp.equalsIgnoreCase("f")); 102 103 XRPaints.register(this); 104 105 initResources(surface); 106 107 maskBuffer = new MaskTileManager(this, surface.getXid()); 108 textRenderer = new XRTextRenderer(this); 109 maskImage = new XRMaskImage(this, surface.getXid()); 110 } 111 initResources(XRSurfaceData surface)112 public void initResources(XRSurfaceData surface) { 113 int parentXid = surface.getXid(); 114 115 solidSrc32 = new XRSolidSrcPict(con, parentXid); 116 setForeground(0); 117 118 int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1); 119 alphaMaskPict = con.createPicture(extraAlphaMask, 120 XRUtils.PictStandardA8); 121 con.setPictureRepeat(alphaMaskPict, XRUtils.RepeatNormal); 122 con.renderRectangle(alphaMaskPict, XRUtils.PictOpClear, 123 XRColor.NO_ALPHA, 0, 0, 1, 1); 124 125 if (enableGradCache) { 126 gradCachePixmap = con.createPixmap(parentXid, 32, 127 MaskTileManager.MASK_SIZE, MaskTileManager.MASK_SIZE); 128 gradCachePicture = con.createPicture(gradCachePixmap, 129 XRUtils.PictStandardARGB32); 130 } 131 } 132 setForeground(int pixel)133 public void setForeground(int pixel) { 134 solidColor.setColorValues(pixel); 135 } 136 setGradientPaint(XRSurfaceData gradient)137 public void setGradientPaint(XRSurfaceData gradient) { 138 if (this.gradient != null) { 139 con.freePicture(this.gradient.picture); 140 } 141 this.gradient = gradient; 142 srcType = GRADIENT; 143 } 144 setTexturePaint(XRSurfaceData texture)145 public void setTexturePaint(XRSurfaceData texture) { 146 this.texture = texture; 147 this.srcType = TEXTURE; 148 } 149 XRResetPaint()150 public void XRResetPaint() { 151 srcType = SOLID; 152 } 153 validateCompositeState(Composite comp, AffineTransform xform, Paint paint, SunGraphics2D sg2d)154 public void validateCompositeState(Composite comp, AffineTransform xform, 155 Paint paint, SunGraphics2D sg2d) { 156 boolean updatePaint = (paint != validatedPaint) || paint == null; 157 158 // validate composite 159 if ((comp != validatedComp)) { 160 if (comp != null) { 161 setComposite(comp); 162 } else { 163 comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER); 164 setComposite(comp); 165 } 166 // the paint state is dependent on the composite state, so make 167 // sure we update the color below 168 updatePaint = true; 169 validatedComp = comp; 170 } 171 172 if (sg2d != null && (validatedPixel != sg2d.pixel || updatePaint)) { 173 validatedPixel = sg2d.pixel; 174 setForeground(validatedPixel); 175 } 176 177 // validate paint 178 if (updatePaint) { 179 if (paint != null && sg2d != null 180 && sg2d.paintState >= SunGraphics2D.PAINT_GRADIENT) { 181 XRPaints.setPaint(sg2d, paint); 182 } else { 183 XRResetPaint(); 184 } 185 validatedPaint = paint; 186 } 187 188 if (srcType != SOLID) { 189 AffineTransform at = (AffineTransform) xform.clone(); 190 try { 191 at.invert(); 192 } catch (NoninvertibleTransformException e) { 193 at.setToIdentity(); 194 } 195 getCurrentSource().validateAsSource(at, -1, XRUtils.ATransOpToXRQuality(sg2d.interpolationType)); 196 } 197 } 198 setComposite(Composite comp)199 private void setComposite(Composite comp) { 200 if (comp instanceof AlphaComposite) { 201 AlphaComposite aComp = (AlphaComposite) comp; 202 validatedExtraAlpha = aComp.getAlpha(); 203 204 this.compRule = XRUtils.j2dAlphaCompToXR(aComp.getRule()); 205 this.extraAlpha = validatedExtraAlpha; 206 207 if (extraAlpha == 1.0f) { 208 alphaMask = XRUtils.None; 209 alphaColor.alpha = XRColor.FULL_ALPHA.alpha; 210 } else { 211 alphaColor.alpha = XRColor 212 .byteToXRColorValue((int) (extraAlpha * 255)); 213 alphaMask = alphaMaskPict; 214 con.renderRectangle(alphaMaskPict, XRUtils.PictOpSrc, 215 alphaColor, 0, 0, 1, 1); 216 } 217 218 xorEnabled = false; 219 } else if (comp instanceof XORComposite) { 220 /* XOR composite validation is handled in XRSurfaceData */ 221 xorEnabled = true; 222 } else { 223 throw new InternalError( 224 "Composite accaleration not implemented for: " 225 + comp.getClass().getName()); 226 } 227 } 228 maskRequired()229 public boolean maskRequired() { 230 return (!xorEnabled) 231 && ((srcType != SOLID) 232 || (srcType == SOLID && (solidColor.alpha != 0xffff) || (extraAlpha != 1.0f))); 233 } 234 XRComposite(int src, int mask, int dst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height)235 public void XRComposite(int src, int mask, int dst, int srcX, int srcY, 236 int maskX, int maskY, int dstX, int dstY, int width, int height) { 237 int cachedSrc = (src == XRUtils.None) ? getCurrentSource().picture : src; 238 int cachedX = srcX; 239 int cachedY = srcY; 240 241 if (enableGradCache && gradient != null 242 && cachedSrc == gradient.picture) { 243 con.renderComposite(XRUtils.PictOpSrc, gradient.picture, 244 XRUtils.None, gradCachePicture, srcX, srcY, 0, 0, 0, 0, 245 width, height); 246 cachedX = 0; 247 cachedY = 0; 248 cachedSrc = gradCachePicture; 249 } 250 251 con.renderComposite(compRule, cachedSrc, mask, dst, cachedX, cachedY, 252 maskX, maskY, dstX, dstY, width, height); 253 } 254 XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects)255 public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) { 256 if (xorEnabled) { 257 con.GCRectangles(dst.getXid(), dst.getGC(), rects); 258 } else { 259 if (rects.getSize() == 1) { 260 con.renderRectangle(dst.getPicture(), compRule, solidColor, 261 rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0)); 262 } else { 263 con.renderRectangles(dst.getPicture(), compRule, solidColor, rects); 264 } 265 } 266 } 267 XRCompositeRectangles(XRSurfaceData dst, GrowableRectArray rects)268 public void XRCompositeRectangles(XRSurfaceData dst, GrowableRectArray rects) { 269 int srcPict = getCurrentSource().picture; 270 271 for(int i=0; i < rects.getSize(); i++) { 272 int x = rects.getX(i); 273 int y = rects.getY(i); 274 int width = rects.getWidth(i); 275 int height = rects.getHeight(i); 276 277 con.renderComposite(compRule, srcPict, XRUtils.None, dst.picture, x, y, 0, 0, x, y, width, height); 278 } 279 } 280 getCurrentSource()281 protected XRSurfaceData getCurrentSource() { 282 switch(srcType) { 283 case SOLID: 284 return solidSrc32.prepareSrcPict(validatedPixel); 285 case TEXTURE: 286 return texture; 287 case GRADIENT: 288 return gradient; 289 } 290 291 return null; 292 } 293 compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx, int sy, int dx, int dy, int w, int h)294 public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx, 295 int sy, int dx, int dy, int w, int h) { 296 con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx, 297 sy, 0, 0, dx, dy, w, h); 298 } 299 compositeText(XRSurfaceData dst, int sx, int sy, int glyphSet, int maskFormat, GrowableEltArray elts)300 public void compositeText(XRSurfaceData dst, int sx, int sy, int glyphSet, 301 int maskFormat, GrowableEltArray elts) { 302 /* 303 * Try to emulate the SRC blend mode with SRC_OVER. 304 * We bail out during pipe validation for cases where this is not possible. 305 */ 306 byte textCompRule = (compRule != XRUtils.PictOpSrc) ? compRule : XRUtils.PictOpOver; 307 con.XRenderCompositeText(textCompRule, getCurrentSource().picture, dst.picture, 308 maskFormat, sx, sy, 0, 0, glyphSet, elts); 309 } 310 getMaskColor()311 public XRColor getMaskColor() { 312 return !isTexturePaintActive() ? XRColor.FULL_ALPHA : getAlphaColor(); 313 } 314 getExtraAlphaMask()315 public int getExtraAlphaMask() { 316 return alphaMask; 317 } 318 isTexturePaintActive()319 public boolean isTexturePaintActive() { 320 return srcType == TEXTURE; 321 } 322 isSolidPaintActive()323 public boolean isSolidPaintActive() { 324 return srcType == SOLID; 325 } 326 getAlphaColor()327 public XRColor getAlphaColor() { 328 return alphaColor; 329 } 330 getBackend()331 public XRBackend getBackend() { 332 return con; 333 } 334 getExtraAlpha()335 public float getExtraAlpha() { 336 return validatedExtraAlpha; 337 } 338 getCompRule()339 public byte getCompRule() { 340 return compRule; 341 } 342 getTextRenderer()343 public XRTextRenderer getTextRenderer() { 344 return textRenderer; 345 } 346 getMaskBuffer()347 public MaskTileManager getMaskBuffer() { 348 return maskBuffer; 349 } 350 getMaskImage()351 public XRMaskImage getMaskImage() { 352 return maskImage; 353 } 354 } 355