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