1 /* 2 * Copyright (c) 2010, 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 sun.awt.SunToolkit; 29 import sun.awt.image.*; 30 import sun.java2d.loops.*; 31 import sun.java2d.pipe.*; 32 import sun.java2d.*; 33 import java.awt.*; 34 import java.awt.geom.*; 35 import java.lang.ref.*; 36 37 public class XRPMBlitLoops { 38 39 static WeakReference<SunVolatileImage> argbTmpPM = new WeakReference<SunVolatileImage>(null); 40 static WeakReference<SunVolatileImage> rgbTmpPM = new WeakReference<SunVolatileImage>(null); 41 42 public XRPMBlitLoops() { 43 } 44 45 public static void register() { 46 GraphicsPrimitive[] primitives = { new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11), 47 new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11), 48 new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11), 49 new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11), 50 51 new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11), 52 new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11), 53 new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11), 54 new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11), 55 56 new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11), 57 new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11), 58 new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11), 59 new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11), 60 61 /* SW -> Surface Blits */ 62 new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11), 63 new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11), 64 new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11), 65 new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11), 66 new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11), 67 new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11), 68 new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11), 69 70 new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11), 71 new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11), 72 new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11), 73 new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11), 74 new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11), 75 new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11), 76 new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), 77 78 /* SW->Surface Scales */ 79 new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11), 80 new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11), 81 new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11), 82 new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11), 83 new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11), 84 new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11), 85 new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11), 86 87 new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11), 88 new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11), 89 new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11), 90 new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11), 91 new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11), 92 new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11), 93 new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), 94 95 /* SW->Surface Transforms */ 96 new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11), 97 new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11), 98 new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11), 99 new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11), 100 new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11), 101 new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11), 102 new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11), 103 104 new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11), 105 new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11), 106 new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11), 107 new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11), 108 new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11), 109 new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11), 110 new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), }; 111 GraphicsPrimitiveMgr.register(primitives); 112 } 113 114 /** 115 * Caches a SW surface using a temporary pixmap. The pixmap is held by a WeakReference, 116 * allowing it to shrink again after some time. 117 */ 118 protected static XRSurfaceData cacheToTmpSurface(SurfaceData src, XRSurfaceData dst, int w, int h, int sx, int sy) { 119 SunVolatileImage vImg; 120 SurfaceType vImgSurfaceType; 121 122 if (src.getTransparency() == Transparency.OPAQUE) { 123 vImg = rgbTmpPM.get(); 124 vImgSurfaceType = SurfaceType.IntRgb; 125 } else { 126 vImg = argbTmpPM.get(); 127 vImgSurfaceType = SurfaceType.IntArgbPre; 128 } 129 130 if (vImg == null || vImg.getWidth() < w || vImg.getHeight() < h) { 131 if (vImg != null) { 132 vImg.flush(); 133 } 134 vImg = (SunVolatileImage) dst.getGraphicsConfig().createCompatibleVolatileImage(w, h, src.getTransparency()); 135 vImg.setAccelerationPriority(1.0f); 136 137 if (src.getTransparency() == SurfaceData.OPAQUE) { 138 rgbTmpPM = new WeakReference<SunVolatileImage>(vImg); 139 } else { 140 argbTmpPM = new WeakReference<SunVolatileImage>(vImg); 141 } 142 } 143 144 Blit swToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, vImgSurfaceType); 145 XRSurfaceData vImgSurface = (XRSurfaceData) vImg.getDestSurface(); 146 swToSurfaceBlit.Blit(src, vImgSurface, AlphaComposite.Src, null, 147 sx, sy, 0, 0, w, h); 148 149 return vImgSurface; 150 } 151 } 152 153 class XRPMBlit extends Blit { 154 public XRPMBlit(SurfaceType srcType, SurfaceType dstType) { 155 super(srcType, CompositeType.AnyAlpha, dstType); 156 } 157 158 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 159 try { 160 SunToolkit.awtLock(); 161 162 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 163 x11sdDst.validateAsDestination(null, clip); 164 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 165 x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST); 166 167 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 168 169 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h); 170 } finally { 171 SunToolkit.awtUnlock(); 172 } 173 } 174 } 175 176 class XRPMScaledBlit extends ScaledBlit { 177 public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { 178 super(srcType, CompositeType.AnyAlpha, dstType); 179 } 180 181 /* 182 * TODO: This breaks scales with non-integer coordinates!?!?! 183 */ 184 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 185 double dx2, double dy2) { 186 try { 187 SunToolkit.awtLock(); 188 189 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 190 x11sdDst.validateAsDestination(null, clip); 191 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 192 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 193 194 double xScale = (dx2 - dx1) / (sx2 - sx1); 195 double yScale = (dy2 - dy1) / (sy2 - sy1); 196 197 sx1 *= xScale; 198 sx2 *= xScale; 199 sy1 *= yScale; 200 sy2 *= yScale; 201 202 AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale); 203 204 x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); /* 205 * TODO: 206 * padded 207 * blit 208 * required 209 * : 210 * - 211 * / 212 * ? 213 * ? 214 */ 215 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1)); 216 } finally { 217 SunToolkit.awtUnlock(); 218 } 219 } 220 } 221 222 /** 223 * Called also if scale+transform is set 224 * 225 * @author Clemens Eisserer 226 */ 227 class XRPMTransformedBlit extends TransformBlit { 228 229 public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 230 super(srcType, CompositeType.AnyAlpha, dstType); 231 } 232 233 /* 234 * Calculates the composite-rectangle required for transformed blits. This 235 * method is functionally equal to: Shape shp = 236 * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds(); 237 * but performs significantly better. 238 */ 239 public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) { 240 double[] compBounds = new double[8]; 241 compBounds[0] = dstx; 242 compBounds[1] = dsty; 243 compBounds[2] = dstx + width; 244 compBounds[3] = dsty; 245 compBounds[4] = dstx + width; 246 compBounds[5] = dsty + height; 247 compBounds[6] = dstx; 248 compBounds[7] = dsty + height; 249 250 tr.transform(compBounds, 0, compBounds, 0, 4); 251 252 double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6]))); 253 double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7]))); 254 double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6]))); 255 double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7]))); 256 257 minX = Math.floor(minX); 258 minY = Math.floor(minY); 259 maxX = Math.ceil(maxX); 260 maxY = Math.ceil(maxY); 261 262 return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY)); 263 } 264 265 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy, 266 int dstx, int dsty, int width, int height) { 267 try { 268 SunToolkit.awtLock(); 269 270 int filter = XRUtils.ATransOpToXRQuality(hint); 271 272 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 273 x11sdDst.validateAsDestination(null, clip); 274 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 275 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 276 277 Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height); 278 279 AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y)); 280 trx.concatenate(xform); 281 AffineTransform maskTX = (AffineTransform) trx.clone(); 282 283 trx.translate(-srcx, -srcy); 284 285 try { 286 trx.invert(); 287 } catch (NoninvertibleTransformException ex) { 288 trx.setToIdentity(); 289 System.err.println("Reseted to identity!"); 290 } 291 292 boolean omitMask = isMaskOmittable(trx, comp, filter); 293 294 if (!omitMask) { 295 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); 296 297 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); 298 int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height); 299 x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture, 300 0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); 301 } else { 302 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; 303 304 x11sdSrc.validateAsSource(trx, repeat, filter); 305 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); 306 } 307 } finally { 308 SunToolkit.awtUnlock(); 309 } 310 } 311 312 /* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */ 313 protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) { 314 return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /* 315 * If 316 * translate 317 * is 318 * integer 319 * only 320 */ 321 && trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only 322 // 90 degree 323 // rotation 324 || trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No 325 // ExtraAlpha!=1 326 } 327 } 328 329 class XrSwToPMBlit extends Blit { 330 Blit pmToSurfaceBlit; 331 332 XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) { 333 super(srcType, CompositeType.AnyAlpha, dstType); 334 pmToSurfaceBlit = new XRPMBlit(dstType, dstType); 335 } 336 337 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 338 /* 339 * If the blit is write-only (putimge), no need for a temporary VI. 340 */ 341 if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) { 342 Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType()); 343 opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 344 } else { 345 try { 346 SunToolkit.awtLock(); 347 348 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 349 pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h); 350 } finally { 351 SunToolkit.awtUnlock(); 352 } 353 } 354 } 355 } 356 357 class XrSwToPMScaledBlit extends ScaledBlit { 358 ScaledBlit pmToSurfaceBlit; 359 360 XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { 361 super(srcType, CompositeType.AnyAlpha, dstType); 362 pmToSurfaceBlit = new XRPMScaledBlit(dstType, dstType); 363 } 364 365 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 366 double dx2, double dy2) { 367 { 368 int w = sx2 - sx1; 369 int h = sy2 - sy1; 370 371 try { 372 SunToolkit.awtLock(); 373 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx1, sy1); 374 pmToSurfaceBlit.Scale(vImgSurface, dst, comp, clip, 0, 0, w, h, dx1, dy1, dx2, dy2); 375 } finally { 376 SunToolkit.awtUnlock(); 377 } 378 } 379 } 380 } 381 382 class XrSwToPMTransformedBlit extends TransformBlit { 383 TransformBlit pmToSurfaceBlit; 384 385 XrSwToPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 386 super(srcType, CompositeType.AnyAlpha, dstType); 387 pmToSurfaceBlit = new XRPMTransformedBlit(dstType, dstType); 388 } 389 390 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int sx, int sy, int dstx, 391 int dsty, int w, int h) { 392 try { 393 SunToolkit.awtLock(); 394 395 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 396 pmToSurfaceBlit.Transform(vImgSurface, dst, comp, clip, xform, hint, 0, 0, dstx, dsty, w, h); 397 } finally { 398 SunToolkit.awtUnlock(); 399 } 400 } 401 }