1 /* 2 * Copyright (c) 2010, 2014, 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 @SuppressWarnings("cast") 182 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 183 double dx2, double dy2) { 184 try { 185 SunToolkit.awtLock(); 186 187 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 188 x11sdDst.validateAsDestination(null, clip); 189 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 190 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 191 192 double xScale = (dx2 - dx1) / (sx2 - sx1); 193 double yScale = (dy2 - dy1) / (sy2 - sy1); 194 195 sx1 *= xScale; 196 sx2 *= xScale; 197 sy1 *= yScale; 198 sy2 *= yScale; 199 200 dx1 = Math.ceil(dx1 - 0.5); 201 dy1 = Math.ceil(dy1 - 0.5); 202 dx2 = Math.ceil(dx2 - 0.5); 203 dy2 = Math.ceil(dy2 - 0.5); 204 205 AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale); 206 207 x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); 208 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1)); 209 } finally { 210 SunToolkit.awtUnlock(); 211 } 212 } 213 } 214 215 /** 216 * Called also if scale+transform is set 217 * 218 * @author Clemens Eisserer 219 */ 220 class XRPMTransformedBlit extends TransformBlit { 221 final Rectangle compositeBounds = new Rectangle(); 222 final double[] srcCoords = new double[8]; 223 final double[] dstCoords = new double[8]; 224 225 public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 226 super(srcType, CompositeType.AnyAlpha, dstType); 227 } 228 229 /* 230 * Calculates the composition-rectangle required for transformed blits. 231 * For composite operations where the composition-rectangle defines 232 * the modified destination area, coordinates are rounded. 233 * Otherwise the composition window rectangle is sized large enough 234 * to not clip away any pixels. 235 */ 236 protected void adjustCompositeBounds(boolean isQuadrantRotated, AffineTransform tr, 237 int dstx, int dsty, int width, int height) { 238 srcCoords[0] = dstx; 239 srcCoords[1] = dsty; 240 srcCoords[2] = dstx + width; 241 srcCoords[3] = dsty + height; 242 243 double minX, minY, maxX, maxY; 244 if (isQuadrantRotated) { 245 tr.transform(srcCoords, 0, dstCoords, 0, 2); 246 247 minX = Math.min(dstCoords[0], dstCoords[2]); 248 minY = Math.min(dstCoords[1], dstCoords[3]); 249 maxX = Math.max(dstCoords[0], dstCoords[2]); 250 maxY = Math.max(dstCoords[1], dstCoords[3]); 251 252 minX = Math.ceil(minX - 0.5); 253 minY = Math.ceil(minY - 0.5); 254 maxX = Math.ceil(maxX - 0.5); 255 maxY = Math.ceil(maxY - 0.5); 256 } else { 257 srcCoords[4] = dstx; 258 srcCoords[5] = dsty + height; 259 srcCoords[6] = dstx + width; 260 srcCoords[7] = dsty; 261 262 tr.transform(srcCoords, 0, dstCoords, 0, 4); 263 264 minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6]))); 265 minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7]))); 266 maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6]))); 267 maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7]))); 268 269 minX = Math.floor(minX); 270 minY = Math.floor(minY); 271 maxX = Math.ceil(maxX); 272 maxY = Math.ceil(maxY); 273 } 274 275 compositeBounds.x = (int) minX; 276 compositeBounds.y = (int) minY; 277 compositeBounds.width = (int) (maxX - minX); 278 compositeBounds.height = (int) (maxY - minY); 279 } 280 281 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, 282 int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) { 283 try { 284 SunToolkit.awtLock(); 285 286 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 287 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 288 XRCompositeManager xrMgr = XRCompositeManager.getInstance(x11sdSrc); 289 290 float extraAlpha = ((AlphaComposite) comp).getAlpha(); 291 int filter = XRUtils.ATransOpToXRQuality(hint); 292 boolean isQuadrantRotated = XRUtils.isTransformQuadrantRotated(xform); 293 294 adjustCompositeBounds(isQuadrantRotated, xform, dstx, dsty, width, height); 295 296 x11sdDst.validateAsDestination(null, clip); 297 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 298 299 AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y); 300 trx.concatenate(xform); 301 AffineTransform maskTX = (AffineTransform) trx.clone(); 302 trx.translate(-srcx, -srcy); 303 304 try { 305 trx.invert(); 306 } catch (NoninvertibleTransformException ex) { 307 trx.setToIdentity(); 308 } 309 310 if (filter != XRUtils.FAST && (!isQuadrantRotated || extraAlpha != 1.0f)) { 311 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); 312 313 // For quadrant-transformed blits geometry is not stored inside the mask 314 // therefore we can use a repeating 1x1 mask for applying extra alpha. 315 int maskPicture = isQuadrantRotated ? xrMgr.getExtraAlphaMask() 316 : mask.prepareBlitMask(x11sdDst, maskTX, width, height); 317 318 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); 319 x11sdDst.maskBuffer.con.renderComposite(xrMgr.getCompRule(), x11sdSrc.picture, 320 maskPicture, x11sdDst.picture, 0, 0, 0, 0, compositeBounds.x, compositeBounds.y, 321 compositeBounds.width, compositeBounds.height); 322 } else { 323 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; 324 325 x11sdSrc.validateAsSource(trx, repeat, filter); 326 327 // compositeBlit takes care of extra alpha 328 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x, 329 compositeBounds.y, compositeBounds.width, compositeBounds.height); 330 } 331 } finally { 332 SunToolkit.awtUnlock(); 333 } 334 } 335 } 336 337 class XrSwToPMBlit extends Blit { 338 Blit pmToSurfaceBlit; 339 340 XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) { 341 super(srcType, CompositeType.AnyAlpha, dstType); 342 pmToSurfaceBlit = new XRPMBlit(dstType, dstType); 343 } 344 345 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 346 // If the blit is write-only (putimge), no need for a temporary VI. 347 if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) { 348 Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType()); 349 opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 350 } else { 351 try { 352 SunToolkit.awtLock(); 353 354 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 355 pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h); 356 } finally { 357 SunToolkit.awtUnlock(); 358 } 359 } 360 } 361 } 362 363 class XrSwToPMScaledBlit extends ScaledBlit { 364 ScaledBlit pmToSurfaceBlit; 365 366 XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { 367 super(srcType, CompositeType.AnyAlpha, dstType); 368 pmToSurfaceBlit = new XRPMScaledBlit(dstType, dstType); 369 } 370 371 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 372 double dx2, double dy2) { 373 { 374 int w = sx2 - sx1; 375 int h = sy2 - sy1; 376 377 try { 378 SunToolkit.awtLock(); 379 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx1, sy1); 380 pmToSurfaceBlit.Scale(vImgSurface, dst, comp, clip, 0, 0, w, h, dx1, dy1, dx2, dy2); 381 } finally { 382 SunToolkit.awtUnlock(); 383 } 384 } 385 } 386 } 387 388 class XrSwToPMTransformedBlit extends TransformBlit { 389 TransformBlit pmToSurfaceBlit; 390 391 XrSwToPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 392 super(srcType, CompositeType.AnyAlpha, dstType); 393 pmToSurfaceBlit = new XRPMTransformedBlit(dstType, dstType); 394 } 395 396 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int sx, int sy, int dstx, 397 int dsty, int w, int h) { 398 try { 399 SunToolkit.awtLock(); 400 401 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 402 pmToSurfaceBlit.Transform(vImgSurface, dst, comp, clip, xform, hint, 0, 0, dstx, dsty, w, h); 403 } finally { 404 SunToolkit.awtUnlock(); 405 } 406 } 407 }