1 /* 2 * Copyright (c) 2019, 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.metal; 27 28 import sun.java2d.SurfaceData; 29 import sun.java2d.loops.*; 30 import sun.java2d.pipe.Region; 31 import sun.java2d.pipe.RenderBuffer; 32 import sun.java2d.pipe.RenderQueue; 33 import sun.java2d.pipe.hw.AccelSurface; 34 35 import java.awt.*; 36 import java.awt.geom.AffineTransform; 37 import java.awt.image.AffineTransformOp; 38 import java.awt.image.BufferedImage; 39 import java.awt.image.BufferedImageOp; 40 import java.lang.annotation.Native; 41 import java.lang.ref.WeakReference; 42 43 import static sun.java2d.pipe.BufferedOpCodes.BLIT; 44 import static sun.java2d.pipe.BufferedOpCodes.SURFACE_TO_SW_BLIT; 45 46 final class MTLBlitLoops { 47 48 static void register() { 49 Blit blitIntArgbPreToSurface = 50 new MTLSwToSurfaceBlit(SurfaceType.IntArgbPre, 51 MTLSurfaceData.PF_INT_ARGB_PRE); 52 Blit blitIntArgbPreToTexture = 53 new MTLSwToTextureBlit(SurfaceType.IntArgbPre, 54 MTLSurfaceData.PF_INT_ARGB_PRE); 55 TransformBlit transformBlitIntArgbPreToSurface = 56 new MTLSwToSurfaceTransform(SurfaceType.IntArgbPre, 57 MTLSurfaceData.PF_INT_ARGB_PRE); 58 MTLSurfaceToSwBlit blitSurfaceToIntArgbPre = 59 new MTLSurfaceToSwBlit(SurfaceType.IntArgbPre, 60 MTLSurfaceData.PF_INT_ARGB_PRE); 61 62 GraphicsPrimitive[] primitives = { 63 // surface->surface ops 64 new MTLSurfaceToSurfaceBlit(), 65 new MTLSurfaceToSurfaceScale(), 66 new MTLSurfaceToSurfaceTransform(), 67 68 // render-to-texture surface->surface ops 69 new MTLRTTSurfaceToSurfaceBlit(), 70 new MTLRTTSurfaceToSurfaceScale(), 71 new MTLRTTSurfaceToSurfaceTransform(), 72 73 // surface->sw ops 74 new MTLSurfaceToSwBlit(SurfaceType.IntArgb, 75 MTLSurfaceData.PF_INT_ARGB), 76 blitSurfaceToIntArgbPre, 77 78 // sw->surface ops 79 blitIntArgbPreToSurface, 80 new MTLSwToSurfaceBlit(SurfaceType.IntRgb, 81 MTLSurfaceData.PF_INT_RGB), 82 new MTLSwToSurfaceBlit(SurfaceType.IntRgbx, 83 MTLSurfaceData.PF_INT_RGBX), 84 new MTLSwToSurfaceBlit(SurfaceType.IntBgr, 85 MTLSurfaceData.PF_INT_BGR), 86 new MTLSwToSurfaceBlit(SurfaceType.IntBgrx, 87 MTLSurfaceData.PF_INT_BGRX), 88 new MTLSwToSurfaceBlit(SurfaceType.ThreeByteBgr, 89 MTLSurfaceData.PF_3BYTE_BGR), 90 new MTLSwToSurfaceBlit(SurfaceType.Ushort565Rgb, 91 MTLSurfaceData.PF_USHORT_565_RGB), 92 new MTLSwToSurfaceBlit(SurfaceType.Ushort555Rgb, 93 MTLSurfaceData.PF_USHORT_555_RGB), 94 new MTLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx, 95 MTLSurfaceData.PF_USHORT_555_RGBX), 96 new MTLSwToSurfaceBlit(SurfaceType.ByteGray, 97 MTLSurfaceData.PF_BYTE_GRAY), 98 new MTLSwToSurfaceBlit(SurfaceType.UshortGray, 99 MTLSurfaceData.PF_USHORT_GRAY), 100 new MTLGeneralBlit(MTLSurfaceData.MTLSurface, 101 CompositeType.AnyAlpha, 102 blitIntArgbPreToSurface), 103 104 new MTLAnyCompositeBlit(MTLSurfaceData.MTLSurface, 105 blitSurfaceToIntArgbPre, 106 blitSurfaceToIntArgbPre, 107 blitIntArgbPreToSurface), 108 new MTLAnyCompositeBlit(SurfaceType.Any, 109 null, 110 blitSurfaceToIntArgbPre, 111 blitIntArgbPreToSurface), 112 113 new MTLSwToSurfaceScale(SurfaceType.IntRgb, 114 MTLSurfaceData.PF_INT_RGB), 115 new MTLSwToSurfaceScale(SurfaceType.IntRgbx, 116 MTLSurfaceData.PF_INT_RGBX), 117 new MTLSwToSurfaceScale(SurfaceType.IntBgr, 118 MTLSurfaceData.PF_INT_BGR), 119 new MTLSwToSurfaceScale(SurfaceType.IntBgrx, 120 MTLSurfaceData.PF_INT_BGRX), 121 new MTLSwToSurfaceScale(SurfaceType.ThreeByteBgr, 122 MTLSurfaceData.PF_3BYTE_BGR), 123 new MTLSwToSurfaceScale(SurfaceType.Ushort565Rgb, 124 MTLSurfaceData.PF_USHORT_565_RGB), 125 new MTLSwToSurfaceScale(SurfaceType.Ushort555Rgb, 126 MTLSurfaceData.PF_USHORT_555_RGB), 127 new MTLSwToSurfaceScale(SurfaceType.Ushort555Rgbx, 128 MTLSurfaceData.PF_USHORT_555_RGBX), 129 new MTLSwToSurfaceScale(SurfaceType.ByteGray, 130 MTLSurfaceData.PF_BYTE_GRAY), 131 new MTLSwToSurfaceScale(SurfaceType.UshortGray, 132 MTLSurfaceData.PF_USHORT_GRAY), 133 new MTLSwToSurfaceScale(SurfaceType.IntArgbPre, 134 MTLSurfaceData.PF_INT_ARGB_PRE), 135 136 new MTLSwToSurfaceTransform(SurfaceType.IntRgb, 137 MTLSurfaceData.PF_INT_RGB), 138 new MTLSwToSurfaceTransform(SurfaceType.IntRgbx, 139 MTLSurfaceData.PF_INT_RGBX), 140 new MTLSwToSurfaceTransform(SurfaceType.IntBgr, 141 MTLSurfaceData.PF_INT_BGR), 142 new MTLSwToSurfaceTransform(SurfaceType.IntBgrx, 143 MTLSurfaceData.PF_INT_BGRX), 144 new MTLSwToSurfaceTransform(SurfaceType.ThreeByteBgr, 145 MTLSurfaceData.PF_3BYTE_BGR), 146 new MTLSwToSurfaceTransform(SurfaceType.Ushort565Rgb, 147 MTLSurfaceData.PF_USHORT_565_RGB), 148 new MTLSwToSurfaceTransform(SurfaceType.Ushort555Rgb, 149 MTLSurfaceData.PF_USHORT_555_RGB), 150 new MTLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx, 151 MTLSurfaceData.PF_USHORT_555_RGBX), 152 new MTLSwToSurfaceTransform(SurfaceType.ByteGray, 153 MTLSurfaceData.PF_BYTE_GRAY), 154 new MTLSwToSurfaceTransform(SurfaceType.UshortGray, 155 MTLSurfaceData.PF_USHORT_GRAY), 156 transformBlitIntArgbPreToSurface, 157 158 new MTLGeneralTransformedBlit(transformBlitIntArgbPreToSurface), 159 160 // texture->surface ops 161 new MTLTextureToSurfaceBlit(), 162 new MTLTextureToSurfaceScale(), 163 new MTLTextureToSurfaceTransform(), 164 165 // sw->texture ops 166 blitIntArgbPreToTexture, 167 new MTLSwToTextureBlit(SurfaceType.IntRgb, 168 MTLSurfaceData.PF_INT_RGB), 169 new MTLSwToTextureBlit(SurfaceType.IntRgbx, 170 MTLSurfaceData.PF_INT_RGBX), 171 new MTLSwToTextureBlit(SurfaceType.IntBgr, 172 MTLSurfaceData.PF_INT_BGR), 173 new MTLSwToTextureBlit(SurfaceType.IntBgrx, 174 MTLSurfaceData.PF_INT_BGRX), 175 new MTLSwToTextureBlit(SurfaceType.ThreeByteBgr, 176 MTLSurfaceData.PF_3BYTE_BGR), 177 new MTLSwToTextureBlit(SurfaceType.Ushort565Rgb, 178 MTLSurfaceData.PF_USHORT_565_RGB), 179 new MTLSwToTextureBlit(SurfaceType.Ushort555Rgb, 180 MTLSurfaceData.PF_USHORT_555_RGB), 181 new MTLSwToTextureBlit(SurfaceType.Ushort555Rgbx, 182 MTLSurfaceData.PF_USHORT_555_RGBX), 183 new MTLSwToTextureBlit(SurfaceType.ByteGray, 184 MTLSurfaceData.PF_BYTE_GRAY), 185 new MTLSwToTextureBlit(SurfaceType.UshortGray, 186 MTLSurfaceData.PF_USHORT_GRAY), 187 new MTLGeneralBlit(MTLSurfaceData.MTLTexture, 188 CompositeType.SrcNoEa, 189 blitIntArgbPreToTexture), 190 }; 191 GraphicsPrimitiveMgr.register(primitives); 192 } 193 194 /** 195 * The following offsets are used to pack the parameters in 196 * createPackedParams(). (They are also used at the native level when 197 * unpacking the params.) 198 */ 199 @Native private static final int OFFSET_SRCTYPE = 16; 200 @Native private static final int OFFSET_HINT = 8; 201 @Native private static final int OFFSET_TEXTURE = 3; 202 @Native private static final int OFFSET_RTT = 2; 203 @Native private static final int OFFSET_XFORM = 1; 204 @Native private static final int OFFSET_ISOBLIT = 0; 205 206 /** 207 * Packs the given parameters into a single int value in order to save 208 * space on the rendering queue. 209 */ 210 private static int createPackedParams(boolean isoblit, boolean texture, 211 boolean rtt, boolean xform, 212 int hint, int srctype) 213 { 214 return 215 ((srctype << OFFSET_SRCTYPE) | 216 (hint << OFFSET_HINT ) | 217 ((texture ? 1 : 0) << OFFSET_TEXTURE) | 218 ((rtt ? 1 : 0) << OFFSET_RTT ) | 219 ((xform ? 1 : 0) << OFFSET_XFORM ) | 220 ((isoblit ? 1 : 0) << OFFSET_ISOBLIT)); 221 } 222 223 /** 224 * Enqueues a BLIT operation with the given parameters. Note that the 225 * RenderQueue lock must be held before calling this method. 226 */ 227 private static void enqueueBlit(RenderQueue rq, 228 SurfaceData src, SurfaceData dst, 229 int packedParams, 230 int sx1, int sy1, 231 int sx2, int sy2, 232 double dx1, double dy1, 233 double dx2, double dy2) 234 { 235 // assert rq.lock.isHeldByCurrentThread(); 236 RenderBuffer buf = rq.getBuffer(); 237 rq.ensureCapacityAndAlignment(72, 24); 238 buf.putInt(BLIT); 239 buf.putInt(packedParams); 240 buf.putInt(sx1).putInt(sy1); 241 buf.putInt(sx2).putInt(sy2); 242 buf.putDouble(dx1).putDouble(dy1); 243 buf.putDouble(dx2).putDouble(dy2); 244 buf.putLong(src.getNativeOps()); 245 buf.putLong(dst.getNativeOps()); 246 } 247 248 static void Blit(SurfaceData srcData, SurfaceData dstData, 249 Composite comp, Region clip, 250 AffineTransform xform, int hint, 251 int sx1, int sy1, 252 int sx2, int sy2, 253 double dx1, double dy1, 254 double dx2, double dy2, 255 int srctype, boolean texture) 256 { 257 int ctxflags = 0; 258 if (srcData.getTransparency() == Transparency.OPAQUE) { 259 ctxflags |= MTLContext.SRC_IS_OPAQUE; 260 } 261 262 MTLRenderQueue rq = MTLRenderQueue.getInstance(); 263 rq.lock(); 264 try { 265 // make sure the RenderQueue keeps a hard reference to the 266 // source (sysmem) SurfaceData to prevent it from being 267 // disposed while the operation is processed on the QFT 268 rq.addReference(srcData); 269 270 MTLSurfaceData oglDst = (MTLSurfaceData)dstData; 271 if (texture) { 272 // make sure we have a current context before uploading 273 // the sysmem data to the texture object 274 MTLGraphicsConfig gc = oglDst.getMTLGraphicsConfig(); 275 MTLContext.setScratchSurface(gc); 276 } else { 277 MTLContext.validateContext(oglDst, oglDst, 278 clip, comp, xform, null, null, 279 ctxflags); 280 } 281 282 int packedParams = createPackedParams(false, texture, 283 false, xform != null, 284 hint, srctype); 285 enqueueBlit(rq, srcData, dstData, 286 packedParams, 287 sx1, sy1, sx2, sy2, 288 dx1, dy1, dx2, dy2); 289 290 // always flush immediately, since we (currently) have no means 291 // of tracking changes to the system memory surface 292 rq.flushNow(); 293 } finally { 294 rq.unlock(); 295 } 296 } 297 298 /** 299 * Note: The srcImg and biop parameters are only used when invoked 300 * from the MTLBufImgOps.renderImageWithOp() method; in all other cases, 301 * this method can be called with null values for those two parameters, 302 * and they will be effectively ignored. 303 */ 304 static void IsoBlit(SurfaceData srcData, SurfaceData dstData, 305 BufferedImage srcImg, BufferedImageOp biop, 306 Composite comp, Region clip, 307 AffineTransform xform, int hint, 308 int sx1, int sy1, 309 int sx2, int sy2, 310 double dx1, double dy1, 311 double dx2, double dy2, 312 boolean texture) 313 { 314 int ctxflags = 0; 315 if (srcData.getTransparency() == Transparency.OPAQUE) { 316 ctxflags |= MTLContext.SRC_IS_OPAQUE; 317 } 318 319 MTLRenderQueue rq = MTLRenderQueue.getInstance(); 320 rq.lock(); 321 try { 322 MTLSurfaceData oglSrc = (MTLSurfaceData)srcData; 323 MTLSurfaceData oglDst = (MTLSurfaceData)dstData; 324 int srctype = oglSrc.getType(); 325 boolean rtt; 326 MTLSurfaceData srcCtxData; 327 if (srctype == MTLSurfaceData.TEXTURE) { 328 // the source is a regular texture object; we substitute 329 // the destination surface for the purposes of making a 330 // context current 331 rtt = false; 332 srcCtxData = oglDst; 333 } else { 334 // the source is a pbuffer, backbuffer, or render-to-texture 335 // surface; we set rtt to true to differentiate this kind 336 // of surface from a regular texture object 337 rtt = true; 338 if (srctype == AccelSurface.RT_TEXTURE) { 339 srcCtxData = oglDst; 340 } else { 341 srcCtxData = oglSrc; 342 } 343 } 344 345 MTLContext.validateContext(srcCtxData, oglDst, 346 clip, comp, xform, null, null, 347 ctxflags); 348 349 if (biop != null) { 350 MTLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop); 351 } 352 353 int packedParams = createPackedParams(true, texture, 354 rtt, xform != null, 355 hint, 0 /*unused*/); 356 enqueueBlit(rq, srcData, dstData, 357 packedParams, 358 sx1, sy1, sx2, sy2, 359 dx1, dy1, dx2, dy2); 360 361 if (biop != null) { 362 MTLBufImgOps.disableBufImgOp(rq, biop); 363 } 364 365 if (rtt && oglDst.isOnScreen()) { 366 // we only have to flush immediately when copying from a 367 // (non-texture) surface to the screen; otherwise Swing apps 368 // might appear unresponsive until the auto-flush completes 369 rq.flushNow(); 370 } 371 } finally { 372 rq.unlock(); 373 } 374 } 375 } 376 377 class MTLSurfaceToSurfaceBlit extends Blit { 378 379 MTLSurfaceToSurfaceBlit() { 380 super(MTLSurfaceData.MTLSurface, 381 CompositeType.AnyAlpha, 382 MTLSurfaceData.MTLSurface); 383 } 384 385 public void Blit(SurfaceData src, SurfaceData dst, 386 Composite comp, Region clip, 387 int sx, int sy, int dx, int dy, int w, int h) 388 { 389 MTLBlitLoops.IsoBlit(src, dst, 390 null, null, 391 comp, clip, null, 392 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 393 sx, sy, sx+w, sy+h, 394 dx, dy, dx+w, dy+h, 395 false); 396 } 397 } 398 399 class MTLSurfaceToSurfaceScale extends ScaledBlit { 400 401 MTLSurfaceToSurfaceScale() { 402 super(MTLSurfaceData.MTLSurface, 403 CompositeType.AnyAlpha, 404 MTLSurfaceData.MTLSurface); 405 } 406 407 public void Scale(SurfaceData src, SurfaceData dst, 408 Composite comp, Region clip, 409 int sx1, int sy1, 410 int sx2, int sy2, 411 double dx1, double dy1, 412 double dx2, double dy2) 413 { 414 MTLBlitLoops.IsoBlit(src, dst, 415 null, null, 416 comp, clip, null, 417 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 418 sx1, sy1, sx2, sy2, 419 dx1, dy1, dx2, dy2, 420 false); 421 } 422 } 423 424 class MTLSurfaceToSurfaceTransform extends TransformBlit { 425 426 MTLSurfaceToSurfaceTransform() { 427 super(MTLSurfaceData.MTLSurface, 428 CompositeType.AnyAlpha, 429 MTLSurfaceData.MTLSurface); 430 } 431 432 public void Transform(SurfaceData src, SurfaceData dst, 433 Composite comp, Region clip, 434 AffineTransform at, int hint, 435 int sx, int sy, int dx, int dy, 436 int w, int h) 437 { 438 MTLBlitLoops.IsoBlit(src, dst, 439 null, null, 440 comp, clip, at, hint, 441 sx, sy, sx+w, sy+h, 442 dx, dy, dx+w, dy+h, 443 false); 444 } 445 } 446 447 class MTLRTTSurfaceToSurfaceBlit extends Blit { 448 449 MTLRTTSurfaceToSurfaceBlit() { 450 super(MTLSurfaceData.MTLSurfaceRTT, 451 CompositeType.AnyAlpha, 452 MTLSurfaceData.MTLSurface); 453 } 454 455 public void Blit(SurfaceData src, SurfaceData dst, 456 Composite comp, Region clip, 457 int sx, int sy, int dx, int dy, int w, int h) 458 { 459 MTLBlitLoops.IsoBlit(src, dst, 460 null, null, 461 comp, clip, null, 462 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 463 sx, sy, sx+w, sy+h, 464 dx, dy, dx+w, dy+h, 465 true); 466 } 467 } 468 469 class MTLRTTSurfaceToSurfaceScale extends ScaledBlit { 470 471 MTLRTTSurfaceToSurfaceScale() { 472 super(MTLSurfaceData.MTLSurfaceRTT, 473 CompositeType.AnyAlpha, 474 MTLSurfaceData.MTLSurface); 475 } 476 477 public void Scale(SurfaceData src, SurfaceData dst, 478 Composite comp, Region clip, 479 int sx1, int sy1, 480 int sx2, int sy2, 481 double dx1, double dy1, 482 double dx2, double dy2) 483 { 484 MTLBlitLoops.IsoBlit(src, dst, 485 null, null, 486 comp, clip, null, 487 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 488 sx1, sy1, sx2, sy2, 489 dx1, dy1, dx2, dy2, 490 true); 491 } 492 } 493 494 class MTLRTTSurfaceToSurfaceTransform extends TransformBlit { 495 496 MTLRTTSurfaceToSurfaceTransform() { 497 super(MTLSurfaceData.MTLSurfaceRTT, 498 CompositeType.AnyAlpha, 499 MTLSurfaceData.MTLSurface); 500 } 501 502 public void Transform(SurfaceData src, SurfaceData dst, 503 Composite comp, Region clip, 504 AffineTransform at, int hint, 505 int sx, int sy, int dx, int dy, int w, int h) 506 { 507 MTLBlitLoops.IsoBlit(src, dst, 508 null, null, 509 comp, clip, at, hint, 510 sx, sy, sx+w, sy+h, 511 dx, dy, dx+w, dy+h, 512 true); 513 } 514 } 515 516 final class MTLSurfaceToSwBlit extends Blit { 517 518 private final int typeval; 519 private WeakReference<SurfaceData> srcTmp; 520 521 // destination will actually be ArgbPre or Argb 522 MTLSurfaceToSwBlit(final SurfaceType dstType, final int typeval) { 523 super(MTLSurfaceData.MTLSurface, 524 CompositeType.SrcNoEa, 525 dstType); 526 this.typeval = typeval; 527 } 528 529 private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, 530 Composite comp, Region clip, 531 int sx, int sy, int dx, int dy, 532 int w, int h) { 533 SurfaceData cachedSrc = null; 534 if (srcTmp != null) { 535 // use cached intermediate surface, if available 536 cachedSrc = srcTmp.get(); 537 } 538 539 // We can convert argb_pre data from MTL surface in two places: 540 // - During MTL surface -> SW blit 541 // - During SW -> SW blit 542 // The first one is faster when we use opaque MTL surface, because in 543 // this case we simply skip conversion and use color components as is. 544 // Because of this we align intermediate buffer type with type of 545 // destination not source. 546 final int type = typeval == MTLSurfaceData.PF_INT_ARGB_PRE ? 547 BufferedImage.TYPE_INT_ARGB_PRE : 548 BufferedImage.TYPE_INT_ARGB; 549 550 src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); 551 552 // copy intermediate SW to destination SW using complex clip 553 final Blit performop = Blit.getFromCache(src.getSurfaceType(), 554 CompositeType.SrcNoEa, 555 dst.getSurfaceType()); 556 performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); 557 558 if (src != cachedSrc) { 559 // cache the intermediate surface 560 srcTmp = new WeakReference<>(src); 561 } 562 } 563 564 public void Blit(SurfaceData src, SurfaceData dst, 565 Composite comp, Region clip, 566 int sx, int sy, int dx, int dy, 567 int w, int h) 568 { 569 if (clip != null) { 570 clip = clip.getIntersectionXYWH(dx, dy, w, h); 571 // At the end this method will flush the RenderQueue, we should exit 572 // from it as soon as possible. 573 if (clip.isEmpty()) { 574 return; 575 } 576 sx += clip.getLoX() - dx; 577 sy += clip.getLoY() - dy; 578 dx = clip.getLoX(); 579 dy = clip.getLoY(); 580 w = clip.getWidth(); 581 h = clip.getHeight(); 582 583 if (!clip.isRectangular()) { 584 complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 585 return; 586 } 587 } 588 589 MTLRenderQueue rq = MTLRenderQueue.getInstance(); 590 rq.lock(); 591 try { 592 // make sure the RenderQueue keeps a hard reference to the 593 // destination (sysmem) SurfaceData to prevent it from being 594 // disposed while the operation is processed on the QFT 595 rq.addReference(dst); 596 597 RenderBuffer buf = rq.getBuffer(); 598 MTLContext.validateContext((MTLSurfaceData)src); 599 600 rq.ensureCapacityAndAlignment(48, 32); 601 buf.putInt(SURFACE_TO_SW_BLIT); 602 buf.putInt(sx).putInt(sy); 603 buf.putInt(dx).putInt(dy); 604 buf.putInt(w).putInt(h); 605 buf.putInt(typeval); 606 buf.putLong(src.getNativeOps()); 607 buf.putLong(dst.getNativeOps()); 608 609 // always flush immediately 610 rq.flushNow(); 611 } finally { 612 rq.unlock(); 613 } 614 } 615 } 616 617 class MTLSwToSurfaceBlit extends Blit { 618 619 private int typeval; 620 621 MTLSwToSurfaceBlit(SurfaceType srcType, int typeval) { 622 super(srcType, 623 CompositeType.AnyAlpha, 624 MTLSurfaceData.MTLSurface); 625 this.typeval = typeval; 626 } 627 628 public void Blit(SurfaceData src, SurfaceData dst, 629 Composite comp, Region clip, 630 int sx, int sy, int dx, int dy, int w, int h) 631 { 632 MTLBlitLoops.Blit(src, dst, 633 comp, clip, null, 634 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 635 sx, sy, sx+w, sy+h, 636 dx, dy, dx+w, dy+h, 637 typeval, false); 638 } 639 } 640 641 class MTLSwToSurfaceScale extends ScaledBlit { 642 643 private int typeval; 644 645 MTLSwToSurfaceScale(SurfaceType srcType, int typeval) { 646 super(srcType, 647 CompositeType.AnyAlpha, 648 MTLSurfaceData.MTLSurface); 649 this.typeval = typeval; 650 } 651 652 public void Scale(SurfaceData src, SurfaceData dst, 653 Composite comp, Region clip, 654 int sx1, int sy1, 655 int sx2, int sy2, 656 double dx1, double dy1, 657 double dx2, double dy2) 658 { 659 MTLBlitLoops.Blit(src, dst, 660 comp, clip, null, 661 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 662 sx1, sy1, sx2, sy2, 663 dx1, dy1, dx2, dy2, 664 typeval, false); 665 } 666 } 667 668 class MTLSwToSurfaceTransform extends TransformBlit { 669 670 private int typeval; 671 672 MTLSwToSurfaceTransform(SurfaceType srcType, int typeval) { 673 super(srcType, 674 CompositeType.AnyAlpha, 675 MTLSurfaceData.MTLSurface); 676 this.typeval = typeval; 677 } 678 679 public void Transform(SurfaceData src, SurfaceData dst, 680 Composite comp, Region clip, 681 AffineTransform at, int hint, 682 int sx, int sy, int dx, int dy, int w, int h) 683 { 684 MTLBlitLoops.Blit(src, dst, 685 comp, clip, at, hint, 686 sx, sy, sx+w, sy+h, 687 dx, dy, dx+w, dy+h, 688 typeval, false); 689 } 690 } 691 692 class MTLSwToTextureBlit extends Blit { 693 694 private int typeval; 695 696 MTLSwToTextureBlit(SurfaceType srcType, int typeval) { 697 super(srcType, 698 CompositeType.SrcNoEa, 699 MTLSurfaceData.MTLTexture); 700 this.typeval = typeval; 701 } 702 703 public void Blit(SurfaceData src, SurfaceData dst, 704 Composite comp, Region clip, 705 int sx, int sy, int dx, int dy, int w, int h) 706 { 707 MTLBlitLoops.Blit(src, dst, 708 comp, clip, null, 709 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 710 sx, sy, sx+w, sy+h, 711 dx, dy, dx+w, dy+h, 712 typeval, true); 713 } 714 } 715 716 class MTLTextureToSurfaceBlit extends Blit { 717 718 MTLTextureToSurfaceBlit() { 719 super(MTLSurfaceData.MTLTexture, 720 CompositeType.AnyAlpha, 721 MTLSurfaceData.MTLSurface); 722 } 723 724 public void Blit(SurfaceData src, SurfaceData dst, 725 Composite comp, Region clip, 726 int sx, int sy, int dx, int dy, int w, int h) 727 { 728 MTLBlitLoops.IsoBlit(src, dst, 729 null, null, 730 comp, clip, null, 731 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 732 sx, sy, sx+w, sy+h, 733 dx, dy, dx+w, dy+h, 734 true); 735 } 736 } 737 738 class MTLTextureToSurfaceScale extends ScaledBlit { 739 740 MTLTextureToSurfaceScale() { 741 super(MTLSurfaceData.MTLTexture, 742 CompositeType.AnyAlpha, 743 MTLSurfaceData.MTLSurface); 744 } 745 746 public void Scale(SurfaceData src, SurfaceData dst, 747 Composite comp, Region clip, 748 int sx1, int sy1, 749 int sx2, int sy2, 750 double dx1, double dy1, 751 double dx2, double dy2) 752 { 753 MTLBlitLoops.IsoBlit(src, dst, 754 null, null, 755 comp, clip, null, 756 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 757 sx1, sy1, sx2, sy2, 758 dx1, dy1, dx2, dy2, 759 true); 760 } 761 } 762 763 class MTLTextureToSurfaceTransform extends TransformBlit { 764 765 MTLTextureToSurfaceTransform() { 766 super(MTLSurfaceData.MTLTexture, 767 CompositeType.AnyAlpha, 768 MTLSurfaceData.MTLSurface); 769 } 770 771 public void Transform(SurfaceData src, SurfaceData dst, 772 Composite comp, Region clip, 773 AffineTransform at, int hint, 774 int sx, int sy, int dx, int dy, 775 int w, int h) 776 { 777 MTLBlitLoops.IsoBlit(src, dst, 778 null, null, 779 comp, clip, at, hint, 780 sx, sy, sx+w, sy+h, 781 dx, dy, dx+w, dy+h, 782 true); 783 } 784 } 785 786 /** 787 * This general Blit implementation converts any source surface to an 788 * intermediate IntArgbPre surface, and then uses the more specific 789 * IntArgbPre->MTLSurface/Texture loop to get the intermediate 790 * (premultiplied) surface down to OpenGL using simple blit. 791 */ 792 class MTLGeneralBlit extends Blit { 793 794 private final Blit performop; 795 private WeakReference<SurfaceData> srcTmp; 796 797 MTLGeneralBlit(SurfaceType dstType, 798 CompositeType compType, 799 Blit performop) 800 { 801 super(SurfaceType.Any, compType, dstType); 802 this.performop = performop; 803 } 804 805 public synchronized void Blit(SurfaceData src, SurfaceData dst, 806 Composite comp, Region clip, 807 int sx, int sy, int dx, int dy, 808 int w, int h) 809 { 810 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 811 CompositeType.SrcNoEa, 812 SurfaceType.IntArgbPre); 813 814 SurfaceData cachedSrc = null; 815 if (srcTmp != null) { 816 // use cached intermediate surface, if available 817 cachedSrc = srcTmp.get(); 818 } 819 820 // convert source to IntArgbPre 821 src = convertFrom(convertsrc, src, sx, sy, w, h, 822 cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE); 823 824 // copy IntArgbPre intermediate surface to OpenGL surface 825 performop.Blit(src, dst, comp, clip, 826 0, 0, dx, dy, w, h); 827 828 if (src != cachedSrc) { 829 // cache the intermediate surface 830 srcTmp = new WeakReference<>(src); 831 } 832 } 833 } 834 835 /** 836 * This general TransformedBlit implementation converts any source surface to an 837 * intermediate IntArgbPre surface, and then uses the more specific 838 * IntArgbPre->MTLSurface/Texture loop to get the intermediate 839 * (premultiplied) surface down to OpenGL using simple transformBlit. 840 */ 841 final class MTLGeneralTransformedBlit extends TransformBlit { 842 843 private final TransformBlit performop; 844 private WeakReference<SurfaceData> srcTmp; 845 846 MTLGeneralTransformedBlit(final TransformBlit performop) { 847 super(SurfaceType.Any, CompositeType.AnyAlpha, 848 MTLSurfaceData.MTLSurface); 849 this.performop = performop; 850 } 851 852 @Override 853 public synchronized void Transform(SurfaceData src, SurfaceData dst, 854 Composite comp, Region clip, 855 AffineTransform at, int hint, int srcx, 856 int srcy, int dstx, int dsty, int width, 857 int height){ 858 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 859 CompositeType.SrcNoEa, 860 SurfaceType.IntArgbPre); 861 // use cached intermediate surface, if available 862 final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; 863 // convert source to IntArgbPre 864 src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, 865 BufferedImage.TYPE_INT_ARGB_PRE); 866 867 // transform IntArgbPre intermediate surface to OpenGL surface 868 performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, 869 width, height); 870 871 if (src != cachedSrc) { 872 // cache the intermediate surface 873 srcTmp = new WeakReference<>(src); 874 } 875 } 876 } 877 878 /** 879 * This general MTLAnyCompositeBlit implementation can convert any source/target 880 * surface to an intermediate surface using convertsrc/convertdst loops, applies 881 * necessary composite operation, and then uses convertresult loop to get the 882 * intermediate surface down to OpenGL. 883 */ 884 final class MTLAnyCompositeBlit extends Blit { 885 886 private WeakReference<SurfaceData> dstTmp; 887 private WeakReference<SurfaceData> srcTmp; 888 private final Blit convertsrc; 889 private final Blit convertdst; 890 private final Blit convertresult; 891 892 MTLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst, 893 Blit convertresult) { 894 super(srctype, CompositeType.Any, MTLSurfaceData.MTLSurface); 895 this.convertsrc = convertsrc; 896 this.convertdst = convertdst; 897 this.convertresult = convertresult; 898 } 899 900 public synchronized void Blit(SurfaceData src, SurfaceData dst, 901 Composite comp, Region clip, 902 int sx, int sy, int dx, int dy, 903 int w, int h) 904 { 905 if (convertsrc != null) { 906 SurfaceData cachedSrc = null; 907 if (srcTmp != null) { 908 // use cached intermediate surface, if available 909 cachedSrc = srcTmp.get(); 910 } 911 // convert source to IntArgbPre 912 src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc, 913 BufferedImage.TYPE_INT_ARGB_PRE); 914 if (src != cachedSrc) { 915 // cache the intermediate surface 916 srcTmp = new WeakReference<>(src); 917 } 918 } 919 920 SurfaceData cachedDst = null; 921 922 if (dstTmp != null) { 923 // use cached intermediate surface, if available 924 cachedDst = dstTmp.get(); 925 } 926 927 // convert destination to IntArgbPre 928 SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h, 929 cachedDst, BufferedImage.TYPE_INT_ARGB_PRE); 930 Region bufferClip = 931 clip == null ? null : clip.getTranslatedRegion(-dx, -dy); 932 933 Blit performop = Blit.getFromCache(src.getSurfaceType(), 934 CompositeType.Any, dstBuffer.getSurfaceType()); 935 performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h); 936 937 if (dstBuffer != cachedDst) { 938 // cache the intermediate surface 939 dstTmp = new WeakReference<>(dstBuffer); 940 } 941 // now blit the buffer back to the destination 942 convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx, 943 dy, w, h); 944 } 945 }