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 sun.font.*; 32 import sun.java2d.*; 33 import sun.java2d.loops.*; 34 35 /** 36 * Manages per-application resources, e.g. the 1x1 pixmap used for solid color 37 * fill as well as per-application state e.g. the currently set source picture 38 * used for composition . 39 * 40 * @author Clemens Eisserer 41 */ 42 43 public class XRCompositeManager { 44 private static XRCompositeManager instance; 45 46 private static final int SOLID = 0; 47 private static final int TEXTURE = 1; 48 private static final int GRADIENT = 2; 49 50 int srcType; 51 XRSolidSrcPict solidSrc32; 52 XRSurfaceData texture; 53 XRSurfaceData gradient; 54 int alphaMask = XRUtils.None; 55 56 XRColor solidColor = new XRColor(); 57 float extraAlpha = 1.0f; 58 byte compRule = XRUtils.PictOpOver; 59 XRColor alphaColor = new XRColor(); 60 61 XRSurfaceData solidSrcPict; 62 int alphaMaskPict; 63 64 boolean xorEnabled = false; 65 int validatedPixel = 0; 66 Composite validatedComp; 67 Paint validatedPaint; 68 float validatedExtraAlpha = 1.0f; 69 70 XRBackend con; 71 RectTileManager maskBuffer; 72 XRTextRenderer textRenderer; 73 XRMaskImage maskImage; 74 75 public static synchronized XRCompositeManager getInstance( 76 XRSurfaceData surface) { 77 if (instance == null) { 78 instance = new XRCompositeManager(surface); 79 } 80 return instance; 81 } 82 83 private XRCompositeManager(XRSurfaceData surface) { 84 String defProp = System.getProperty("sun.java2d.xr.deferred"); 85 86 if(defProp != null && defProp.length() > 0 87 && Character.toLowerCase(defProp.charAt(0)) == 't') { 88 con = new XRBackendDeferred(); 89 } else { 90 con = new XRBackendNative(); 91 } 92 93 con.initResources(surface.getXid()); 94 95 XRPaints.register(this); 96 97 initResources(surface); 98 99 maskBuffer = new RectTileManager(this, surface.getXid()); 100 textRenderer = new XRTextRenderer(this); 101 maskImage = new XRMaskImage(this, surface.getXid()); 102 } 103 104 public void initResources(XRSurfaceData surface) { 105 int parentXid = surface.getXid(); 106 107 solidSrc32 = new XRSolidSrcPict(con, parentXid); 108 setForeground(0); 109 110 int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1); 111 alphaMaskPict = con.createPicture(extraAlphaMask, 112 XRUtils.PictStandardA8); 113 con.setPictureRepeat(alphaMaskPict, XRUtils.RepeatNormal); 114 con.renderRectangle(alphaMaskPict, XRUtils.PictOpClear, 115 XRColor.NO_ALPHA, 0, 0, 1, 1); 116 } 117 118 public void setForeground(int pixel) { 119 solidColor.setColorValues(pixel); 120 } 121 122 public void setGradientPaint(XRSurfaceData gradient) { 123 if (this.gradient != null) { 124 con.freePicture(this.gradient.picture); 125 } 126 this.gradient = gradient; 127 srcType = GRADIENT; 128 } 129 130 public void setTexturePaint(XRSurfaceData texture) { 131 this.texture = texture; 132 this.srcType = TEXTURE; 133 } 134 135 public void XRResetPaint() { 136 srcType = SOLID; 137 } 138 139 public void validateCompositeState(Composite comp, AffineTransform xform, 140 Paint paint, SunGraphics2D sg2d) { 141 boolean updatePaint = (paint != validatedPaint) || paint == null; 142 143 // validate composite 144 if ((comp != validatedComp)) { 145 if (comp != null) { 146 setComposite(comp); 147 } else { 148 comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER); 149 setComposite(comp); 150 } 151 // the paint state is dependent on the composite state, so make 152 // sure we update the color below 153 updatePaint = true; 154 validatedComp = comp; 155 } 156 157 if (sg2d != null && (validatedPixel != sg2d.pixel || updatePaint)) { 158 validatedPixel = sg2d.pixel; 159 setForeground(validatedPixel); 160 } 161 162 // validate paint 163 if (updatePaint) { 164 if (paint != null && sg2d != null 165 && sg2d.paintState >= SunGraphics2D.PAINT_GRADIENT) { 166 XRPaints.setPaint(sg2d, paint); 167 } else { 168 XRResetPaint(); 169 } 170 validatedPaint = paint; 171 } 172 173 if (srcType != SOLID) { 174 AffineTransform at = (AffineTransform) xform.clone(); 175 try { 176 at.invert(); 177 } catch (NoninvertibleTransformException e) { 178 at.setToIdentity(); 179 } 180 getCurrentSource().validateAsSource(at, -1, XRUtils.ATransOpToXRQuality(sg2d.interpolationType)); 181 } 182 } 183 184 private void setComposite(Composite comp) { 185 if (comp instanceof AlphaComposite) { 186 AlphaComposite aComp = (AlphaComposite) comp; 187 validatedExtraAlpha = aComp.getAlpha(); 188 189 this.compRule = XRUtils.j2dAlphaCompToXR(aComp.getRule()); 190 this.extraAlpha = validatedExtraAlpha; 191 192 if (extraAlpha == 1.0f) { 193 alphaMask = XRUtils.None; 194 alphaColor.alpha = XRColor.FULL_ALPHA.alpha; 195 } else { 196 alphaColor.alpha = XRColor 197 .byteToXRColorValue((int) (extraAlpha * 255)); 198 alphaMask = alphaMaskPict; 199 con.renderRectangle(alphaMaskPict, XRUtils.PictOpSrc, 200 alphaColor, 0, 0, 1, 1); 201 } 202 203 xorEnabled = false; 204 } else if (comp instanceof XORComposite) { 205 /* XOR composite validation is handled in XRSurfaceData */ 206 xorEnabled = true; 207 } else { 208 throw new InternalError( 209 "Composite accaleration not implemented for: " 210 + comp.getClass().getName()); 211 } 212 } 213 214 public boolean maskRequired() { 215 return (!xorEnabled) 216 && ((srcType != SOLID) 217 || (srcType == SOLID && (solidColor.alpha != 0xffff) || (extraAlpha != 1.0f))); 218 } 219 220 public void XRComposite(int src, int mask, int dst, int srcX, int srcY, 221 int maskX, int maskY, int dstX, int dstY, int width, int height) { 222 int cachedSrc = (src == XRUtils.None) ? getCurrentSource().picture : src; 223 224 con.renderComposite(compRule, cachedSrc, mask, dst, srcX, srcY, 225 maskX, maskY, dstX, dstY, width, height); 226 } 227 228 public void XRMaskedComposite(int src, int dst, 229 int srcX, int srcY, int dstX, int dstY, int width, 230 int height, int maskScan, int maskOff, byte[] mask) { 231 232 src = (src == XRUtils.None) ? getCurrentSource().picture : src; 233 234 float maskAlpha = 1.0f; 235 int maskXid = XRUtils.None; 236 237 if (mask != null) { 238 maskAlpha = isTexturePaintActive() ? getExtraAlpha() : 1.0f; 239 } else if (isTexturePaintActive()) { 240 maskXid = getExtraAlphaMask(); 241 } 242 243 con.maskedComposite(compRule, src, maskXid, dst, 244 srcX, srcY, dstX, dstY, width, 245 height, maskScan, maskOff, mask, maskAlpha); 246 } 247 248 public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) { 249 if (xorEnabled) { 250 con.GCRectangles(dst.getXid(), dst.getGC(), rects); 251 } else { 252 if (rects.getSize() == 1) { 253 con.renderRectangle(dst.getPicture(), compRule, solidColor, 254 rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0)); 255 } else { 256 con.renderRectangles(dst.getPicture(), compRule, solidColor, rects); 257 } 258 } 259 } 260 261 public void XRCompositeRectangles(XRSurfaceData dst, GrowableRectArray rects) { 262 int srcPict = getCurrentSource().picture; 263 264 for(int i=0; i < rects.getSize(); i++) { 265 int x = rects.getX(i); 266 int y = rects.getY(i); 267 int width = rects.getWidth(i); 268 int height = rects.getHeight(i); 269 270 con.renderComposite(compRule, srcPict, XRUtils.None, dst.picture, x, y, 0, 0, x, y, width, height); 271 } 272 } 273 274 protected XRSurfaceData getCurrentSource() { 275 switch(srcType) { 276 case SOLID: 277 return solidSrc32.prepareSrcPict(validatedPixel); 278 case TEXTURE: 279 return texture; 280 case GRADIENT: 281 return gradient; 282 } 283 284 return null; 285 } 286 287 public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx, 288 int sy, int dx, int dy, int w, int h) { 289 con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx, 290 sy, 0, 0, dx, dy, w, h); 291 } 292 293 public void compositeText(XRSurfaceData dst, int sx, int sy, int glyphSet, 294 int maskFormat, GrowableEltArray elts) { 295 /* 296 * Try to emulate the SRC blend mode with SRC_OVER. 297 * We bail out during pipe validation for cases where this is not possible. 298 */ 299 byte textCompRule = (compRule != XRUtils.PictOpSrc) ? compRule : XRUtils.PictOpOver; 300 con.XRenderCompositeText(textCompRule, getCurrentSource().picture, dst.picture, 301 maskFormat, sx, sy, 0, 0, glyphSet, elts); 302 } 303 304 public XRColor getMaskColor() { 305 return !isTexturePaintActive() ? XRColor.FULL_ALPHA : getAlphaColor(); 306 } 307 308 public int getExtraAlphaMask() { 309 return alphaMask; 310 } 311 312 public boolean isTexturePaintActive() { 313 return srcType == TEXTURE; 314 } 315 316 public boolean isSolidPaintActive() { 317 return srcType == SOLID; 318 } 319 320 public XRColor getAlphaColor() { 321 return alphaColor; 322 } 323 324 public XRBackend getBackend() { 325 return con; 326 } 327 328 public float getExtraAlpha() { 329 return validatedExtraAlpha; 330 } 331 332 public byte getCompRule() { 333 return compRule; 334 } 335 336 public XRTextRenderer getTextRenderer() { 337 return textRenderer; 338 } 339 340 public RectTileManager getMaskBuffer() { 341 return maskBuffer; 342 } 343 344 public XRMaskImage getMaskImage() { 345 return maskImage; 346 } 347 }