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