Path: blob/master/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java
41159 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.metal;2627import sun.java2d.SurfaceData;28import sun.java2d.loops.Blit;29import sun.java2d.loops.CompositeType;30import sun.java2d.loops.GraphicsPrimitive;31import sun.java2d.loops.GraphicsPrimitiveMgr;32import sun.java2d.loops.ScaledBlit;33import sun.java2d.loops.SurfaceType;34import sun.java2d.loops.TransformBlit;35import sun.java2d.pipe.Region;36import sun.java2d.pipe.RenderBuffer;37import sun.java2d.pipe.RenderQueue;38import sun.java2d.pipe.hw.AccelSurface;3940import java.awt.AlphaComposite;41import java.awt.Composite;42import java.awt.Transparency;43import java.awt.geom.AffineTransform;44import java.awt.image.AffineTransformOp;45import java.awt.image.BufferedImage;46import java.awt.image.BufferedImageOp;47import java.lang.annotation.Native;48import java.lang.ref.WeakReference;4950import static sun.java2d.pipe.BufferedOpCodes.BLIT;51import static sun.java2d.pipe.BufferedOpCodes.SURFACE_TO_SW_BLIT;5253final class MTLBlitLoops {5455static void register() {56Blit blitIntArgbPreToSurface =57new MTLSwToSurfaceBlit(SurfaceType.IntArgbPre,58MTLSurfaceData.PF_INT_ARGB_PRE);59Blit blitIntArgbPreToTexture =60new MTLSwToTextureBlit(SurfaceType.IntArgbPre,61MTLSurfaceData.PF_INT_ARGB_PRE);62TransformBlit transformBlitIntArgbPreToSurface =63new MTLSwToSurfaceTransform(SurfaceType.IntArgbPre,64MTLSurfaceData.PF_INT_ARGB_PRE);65MTLSurfaceToSwBlit blitSurfaceToIntArgbPre =66new MTLSurfaceToSwBlit(SurfaceType.IntArgbPre,67MTLSurfaceData.PF_INT_ARGB_PRE);6869GraphicsPrimitive[] primitives = {70// surface->surface ops71new MTLSurfaceToSurfaceBlit(),72new MTLSurfaceToSurfaceScale(),73new MTLSurfaceToSurfaceTransform(),7475// render-to-texture surface->surface ops76new MTLRTTSurfaceToSurfaceBlit(),77new MTLRTTSurfaceToSurfaceScale(),78new MTLRTTSurfaceToSurfaceTransform(),7980// surface->sw ops81new MTLSurfaceToSwBlit(SurfaceType.IntArgb,82MTLSurfaceData.PF_INT_ARGB),83blitSurfaceToIntArgbPre,8485// sw->surface ops86blitIntArgbPreToSurface,87new MTLSwToSurfaceBlit(SurfaceType.IntRgb,88MTLSurfaceData.PF_INT_RGB),89new MTLSwToSurfaceBlit(SurfaceType.IntRgbx,90MTLSurfaceData.PF_INT_RGBX),91new MTLSwToSurfaceBlit(SurfaceType.IntBgr,92MTLSurfaceData.PF_INT_BGR),93new MTLSwToSurfaceBlit(SurfaceType.IntBgrx,94MTLSurfaceData.PF_INT_BGRX),95new MTLGeneralBlit(MTLSurfaceData.MTLSurface,96CompositeType.AnyAlpha,97blitIntArgbPreToSurface),9899new MTLAnyCompositeBlit(MTLSurfaceData.MTLSurface,100blitSurfaceToIntArgbPre,101blitSurfaceToIntArgbPre,102blitIntArgbPreToSurface),103new MTLAnyCompositeBlit(SurfaceType.Any,104null,105blitSurfaceToIntArgbPre,106blitIntArgbPreToSurface),107108new MTLSwToSurfaceScale(SurfaceType.IntRgb,109MTLSurfaceData.PF_INT_RGB),110new MTLSwToSurfaceScale(SurfaceType.IntRgbx,111MTLSurfaceData.PF_INT_RGBX),112new MTLSwToSurfaceScale(SurfaceType.IntBgr,113MTLSurfaceData.PF_INT_BGR),114new MTLSwToSurfaceScale(SurfaceType.IntBgrx,115MTLSurfaceData.PF_INT_BGRX),116new MTLSwToSurfaceScale(SurfaceType.IntArgbPre,117MTLSurfaceData.PF_INT_ARGB_PRE),118119new MTLSwToSurfaceTransform(SurfaceType.IntRgb,120MTLSurfaceData.PF_INT_RGB),121new MTLSwToSurfaceTransform(SurfaceType.IntRgbx,122MTLSurfaceData.PF_INT_RGBX),123new MTLSwToSurfaceTransform(SurfaceType.IntBgr,124MTLSurfaceData.PF_INT_BGR),125new MTLSwToSurfaceTransform(SurfaceType.IntBgrx,126MTLSurfaceData.PF_INT_BGRX),127transformBlitIntArgbPreToSurface,128129new MTLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),130131// texture->surface ops132new MTLTextureToSurfaceBlit(),133new MTLTextureToSurfaceScale(),134new MTLTextureToSurfaceTransform(),135136// sw->texture ops137blitIntArgbPreToTexture,138new MTLSwToTextureBlit(SurfaceType.IntRgb,139MTLSurfaceData.PF_INT_RGB),140new MTLSwToTextureBlit(SurfaceType.IntRgbx,141MTLSurfaceData.PF_INT_RGBX),142new MTLSwToTextureBlit(SurfaceType.IntBgr,143MTLSurfaceData.PF_INT_BGR),144new MTLSwToTextureBlit(SurfaceType.IntBgrx,145MTLSurfaceData.PF_INT_BGRX),146new MTLGeneralBlit(MTLSurfaceData.MTLTexture,147CompositeType.SrcNoEa,148blitIntArgbPreToTexture),149};150GraphicsPrimitiveMgr.register(primitives);151}152153/**154* The following offsets are used to pack the parameters in155* createPackedParams(). (They are also used at the native level when156* unpacking the params.)157*/158@Native private static final int OFFSET_SRCTYPE = 16;159@Native private static final int OFFSET_HINT = 8;160@Native private static final int OFFSET_TEXTURE = 3;161@Native private static final int OFFSET_RTT = 2;162@Native private static final int OFFSET_XFORM = 1;163@Native private static final int OFFSET_ISOBLIT = 0;164165/**166* Packs the given parameters into a single int value in order to save167* space on the rendering queue.168*/169private static int createPackedParams(boolean isoblit, boolean texture,170boolean rtt, boolean xform,171int hint, int srctype)172{173return174((srctype << OFFSET_SRCTYPE) |175(hint << OFFSET_HINT ) |176((texture ? 1 : 0) << OFFSET_TEXTURE) |177((rtt ? 1 : 0) << OFFSET_RTT ) |178((xform ? 1 : 0) << OFFSET_XFORM ) |179((isoblit ? 1 : 0) << OFFSET_ISOBLIT));180}181182/**183* Enqueues a BLIT operation with the given parameters. Note that the184* RenderQueue lock must be held before calling this method.185*/186private static void enqueueBlit(RenderQueue rq,187SurfaceData src, SurfaceData dst,188int packedParams,189int sx1, int sy1,190int sx2, int sy2,191double dx1, double dy1,192double dx2, double dy2)193{194// assert rq.lock.isHeldByCurrentThread();195RenderBuffer buf = rq.getBuffer();196rq.ensureCapacityAndAlignment(72, 24);197buf.putInt(BLIT);198buf.putInt(packedParams);199buf.putInt(sx1).putInt(sy1);200buf.putInt(sx2).putInt(sy2);201buf.putDouble(dx1).putDouble(dy1);202buf.putDouble(dx2).putDouble(dy2);203buf.putLong(src.getNativeOps());204buf.putLong(dst.getNativeOps());205}206207static void Blit(SurfaceData srcData, SurfaceData dstData,208Composite comp, Region clip,209AffineTransform xform, int hint,210int sx1, int sy1,211int sx2, int sy2,212double dx1, double dy1,213double dx2, double dy2,214int srctype, boolean texture)215{216int ctxflags = 0;217if (srcData.getTransparency() == Transparency.OPAQUE) {218ctxflags |= MTLContext.SRC_IS_OPAQUE;219}220221MTLRenderQueue rq = MTLRenderQueue.getInstance();222rq.lock();223try {224// make sure the RenderQueue keeps a hard reference to the225// source (sysmem) SurfaceData to prevent it from being226// disposed while the operation is processed on the QFT227rq.addReference(srcData);228229MTLSurfaceData mtlDst = (MTLSurfaceData)dstData;230if (texture) {231// make sure we have a current context before uploading232// the sysmem data to the texture object233MTLGraphicsConfig gc = mtlDst.getMTLGraphicsConfig();234MTLContext.setScratchSurface(gc);235} else {236MTLContext.validateContext(mtlDst, mtlDst,237clip, comp, xform, null, null,238ctxflags);239}240241int packedParams = createPackedParams(false, texture,242false /*unused*/, xform != null,243hint, srctype);244enqueueBlit(rq, srcData, dstData,245packedParams,246sx1, sy1, sx2, sy2,247dx1, dy1, dx2, dy2);248249// always flush immediately, since we (currently) have no means250// of tracking changes to the system memory surface251rq.flushNow();252} finally {253rq.unlock();254}255}256257/**258* Note: The srcImg and biop parameters are only used when invoked259* from the MTLBufImgOps.renderImageWithOp() method; in all other cases,260* this method can be called with null values for those two parameters,261* and they will be effectively ignored.262*/263static void IsoBlit(SurfaceData srcData, SurfaceData dstData,264BufferedImage srcImg, BufferedImageOp biop,265Composite comp, Region clip,266AffineTransform xform, int hint,267int sx1, int sy1,268int sx2, int sy2,269double dx1, double dy1,270double dx2, double dy2,271boolean texture)272{273int ctxflags = 0;274if (srcData.getTransparency() == Transparency.OPAQUE) {275ctxflags |= MTLContext.SRC_IS_OPAQUE;276}277278MTLRenderQueue rq = MTLRenderQueue.getInstance();279rq.lock();280try {281MTLSurfaceData mtlSrc = (MTLSurfaceData)srcData;282MTLSurfaceData mtlDst = (MTLSurfaceData)dstData;283int srctype = mtlSrc.getType();284boolean rtt;285MTLSurfaceData srcCtxData;286if (srctype == MTLSurfaceData.TEXTURE) {287// the source is a regular texture object; we substitute288// the destination surface for the purposes of making a289// context current290rtt = false;291srcCtxData = mtlDst;292} else {293// the source is a pbuffer, backbuffer, or render-to-texture294// surface; we set rtt to true to differentiate this kind295// of surface from a regular texture object296rtt = true;297if (srctype == AccelSurface.RT_TEXTURE) {298srcCtxData = mtlDst;299} else {300srcCtxData = mtlSrc;301}302}303304MTLContext.validateContext(srcCtxData, mtlDst,305clip, comp, xform, null, null,306ctxflags);307308if (biop != null) {309MTLBufImgOps.enableBufImgOp(rq, mtlSrc, srcImg, biop);310}311312int packedParams = createPackedParams(true, texture,313false /*unused*/, xform != null,314hint, 0 /*unused*/);315enqueueBlit(rq, srcData, dstData,316packedParams,317sx1, sy1, sx2, sy2,318dx1, dy1, dx2, dy2);319320if (biop != null) {321MTLBufImgOps.disableBufImgOp(rq, biop);322}323324if (rtt && mtlDst.isOnScreen()) {325// we only have to flush immediately when copying from a326// (non-texture) surface to the screen; otherwise Swing apps327// might appear unresponsive until the auto-flush completes328rq.flushNow();329}330} finally {331rq.unlock();332}333}334}335336class MTLSurfaceToSurfaceBlit extends Blit {337338MTLSurfaceToSurfaceBlit() {339super(MTLSurfaceData.MTLSurface,340CompositeType.AnyAlpha,341MTLSurfaceData.MTLSurface);342}343344public void Blit(SurfaceData src, SurfaceData dst,345Composite comp, Region clip,346int sx, int sy, int dx, int dy, int w, int h)347{348MTLBlitLoops.IsoBlit(src, dst,349null, null,350comp, clip, null,351AffineTransformOp.TYPE_NEAREST_NEIGHBOR,352sx, sy, sx+w, sy+h,353dx, dy, dx+w, dy+h,354false);355}356}357358class MTLSurfaceToSurfaceScale extends ScaledBlit {359360MTLSurfaceToSurfaceScale() {361super(MTLSurfaceData.MTLSurface,362CompositeType.AnyAlpha,363MTLSurfaceData.MTLSurface);364}365366public void Scale(SurfaceData src, SurfaceData dst,367Composite comp, Region clip,368int sx1, int sy1,369int sx2, int sy2,370double dx1, double dy1,371double dx2, double dy2)372{373MTLBlitLoops.IsoBlit(src, dst,374null, null,375comp, clip, null,376AffineTransformOp.TYPE_NEAREST_NEIGHBOR,377sx1, sy1, sx2, sy2,378dx1, dy1, dx2, dy2,379false);380}381}382383class MTLSurfaceToSurfaceTransform extends TransformBlit {384385MTLSurfaceToSurfaceTransform() {386super(MTLSurfaceData.MTLSurface,387CompositeType.AnyAlpha,388MTLSurfaceData.MTLSurface);389}390391public void Transform(SurfaceData src, SurfaceData dst,392Composite comp, Region clip,393AffineTransform at, int hint,394int sx, int sy, int dx, int dy,395int w, int h)396{397MTLBlitLoops.IsoBlit(src, dst,398null, null,399comp, clip, at, hint,400sx, sy, sx+w, sy+h,401dx, dy, dx+w, dy+h,402false);403}404}405406class MTLRTTSurfaceToSurfaceBlit extends Blit {407408MTLRTTSurfaceToSurfaceBlit() {409super(MTLSurfaceData.MTLSurfaceRTT,410CompositeType.AnyAlpha,411MTLSurfaceData.MTLSurface);412}413414public void Blit(SurfaceData src, SurfaceData dst,415Composite comp, Region clip,416int sx, int sy, int dx, int dy, int w, int h)417{418MTLBlitLoops.IsoBlit(src, dst,419null, null,420comp, clip, null,421AffineTransformOp.TYPE_NEAREST_NEIGHBOR,422sx, sy, sx+w, sy+h,423dx, dy, dx+w, dy+h,424true);425}426}427428class MTLRTTSurfaceToSurfaceScale extends ScaledBlit {429430MTLRTTSurfaceToSurfaceScale() {431super(MTLSurfaceData.MTLSurfaceRTT,432CompositeType.AnyAlpha,433MTLSurfaceData.MTLSurface);434}435436public void Scale(SurfaceData src, SurfaceData dst,437Composite comp, Region clip,438int sx1, int sy1,439int sx2, int sy2,440double dx1, double dy1,441double dx2, double dy2)442{443MTLBlitLoops.IsoBlit(src, dst,444null, null,445comp, clip, null,446AffineTransformOp.TYPE_NEAREST_NEIGHBOR,447sx1, sy1, sx2, sy2,448dx1, dy1, dx2, dy2,449true);450}451}452453class MTLRTTSurfaceToSurfaceTransform extends TransformBlit {454455MTLRTTSurfaceToSurfaceTransform() {456super(MTLSurfaceData.MTLSurfaceRTT,457CompositeType.AnyAlpha,458MTLSurfaceData.MTLSurface);459}460461public void Transform(SurfaceData src, SurfaceData dst,462Composite comp, Region clip,463AffineTransform at, int hint,464int sx, int sy, int dx, int dy, int w, int h)465{466MTLBlitLoops.IsoBlit(src, dst,467null, null,468comp, clip, at, hint,469sx, sy, sx+w, sy+h,470dx, dy, dx+w, dy+h,471true);472}473}474475final class MTLSurfaceToSwBlit extends Blit {476477private final int typeval;478private WeakReference<SurfaceData> srcTmp;479480// destination will actually be ArgbPre or Argb481MTLSurfaceToSwBlit(final SurfaceType dstType, final int typeval) {482super(MTLSurfaceData.MTLSurface,483CompositeType.SrcNoEa,484dstType);485this.typeval = typeval;486}487488private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,489Composite comp, Region clip,490int sx, int sy, int dx, int dy,491int w, int h) {492SurfaceData cachedSrc = null;493if (srcTmp != null) {494// use cached intermediate surface, if available495cachedSrc = srcTmp.get();496}497498// We can convert argb_pre data from MTL surface in two places:499// - During MTL surface -> SW blit500// - During SW -> SW blit501// The first one is faster when we use opaque MTL surface, because in502// this case we simply skip conversion and use color components as is.503// Because of this we align intermediate buffer type with type of504// destination not source.505final int type = typeval == MTLSurfaceData.PF_INT_ARGB_PRE ?506BufferedImage.TYPE_INT_ARGB_PRE :507BufferedImage.TYPE_INT_ARGB;508509src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);510511// copy intermediate SW to destination SW using complex clip512final Blit performop = Blit.getFromCache(src.getSurfaceType(),513CompositeType.SrcNoEa,514dst.getSurfaceType());515performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);516517if (src != cachedSrc) {518// cache the intermediate surface519srcTmp = new WeakReference<>(src);520}521}522523public void Blit(SurfaceData src, SurfaceData dst,524Composite comp, Region clip,525int sx, int sy, int dx, int dy,526int w, int h)527{528if (clip != null) {529clip = clip.getIntersectionXYWH(dx, dy, w, h);530// At the end this method will flush the RenderQueue, we should exit531// from it as soon as possible.532if (clip.isEmpty()) {533return;534}535sx += clip.getLoX() - dx;536sy += clip.getLoY() - dy;537dx = clip.getLoX();538dy = clip.getLoY();539w = clip.getWidth();540h = clip.getHeight();541542if (!clip.isRectangular()) {543complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);544return;545}546}547548MTLRenderQueue rq = MTLRenderQueue.getInstance();549rq.lock();550try {551// make sure the RenderQueue keeps a hard reference to the552// destination (sysmem) SurfaceData to prevent it from being553// disposed while the operation is processed on the QFT554rq.addReference(dst);555556RenderBuffer buf = rq.getBuffer();557MTLContext.validateContext((MTLSurfaceData)src);558559rq.ensureCapacityAndAlignment(48, 32);560buf.putInt(SURFACE_TO_SW_BLIT);561buf.putInt(sx).putInt(sy);562buf.putInt(dx).putInt(dy);563buf.putInt(w).putInt(h);564buf.putInt(typeval);565buf.putLong(src.getNativeOps());566buf.putLong(dst.getNativeOps());567568// always flush immediately569rq.flushNow();570} finally {571rq.unlock();572}573}574}575576class MTLSwToSurfaceBlit extends Blit {577578private int typeval;579580MTLSwToSurfaceBlit(SurfaceType srcType, int typeval) {581super(srcType,582CompositeType.AnyAlpha,583MTLSurfaceData.MTLSurface);584this.typeval = typeval;585}586587public void Blit(SurfaceData src, SurfaceData dst,588Composite comp, Region clip,589int sx, int sy, int dx, int dy, int w, int h)590{591MTLBlitLoops.Blit(src, dst,592comp, clip, null,593AffineTransformOp.TYPE_NEAREST_NEIGHBOR,594sx, sy, sx+w, sy+h,595dx, dy, dx+w, dy+h,596typeval, false);597}598}599600class MTLSwToSurfaceScale extends ScaledBlit {601602private int typeval;603604MTLSwToSurfaceScale(SurfaceType srcType, int typeval) {605super(srcType,606CompositeType.AnyAlpha,607MTLSurfaceData.MTLSurface);608this.typeval = typeval;609}610611public void Scale(SurfaceData src, SurfaceData dst,612Composite comp, Region clip,613int sx1, int sy1,614int sx2, int sy2,615double dx1, double dy1,616double dx2, double dy2)617{618MTLBlitLoops.Blit(src, dst,619comp, clip, null,620AffineTransformOp.TYPE_NEAREST_NEIGHBOR,621sx1, sy1, sx2, sy2,622dx1, dy1, dx2, dy2,623typeval, false);624}625}626627class MTLSwToSurfaceTransform extends TransformBlit {628629private int typeval;630631MTLSwToSurfaceTransform(SurfaceType srcType, int typeval) {632super(srcType,633CompositeType.AnyAlpha,634MTLSurfaceData.MTLSurface);635this.typeval = typeval;636}637638public void Transform(SurfaceData src, SurfaceData dst,639Composite comp, Region clip,640AffineTransform at, int hint,641int sx, int sy, int dx, int dy, int w, int h)642{643MTLBlitLoops.Blit(src, dst,644comp, clip, at, hint,645sx, sy, sx+w, sy+h,646dx, dy, dx+w, dy+h,647typeval, false);648}649}650651class MTLSwToTextureBlit extends Blit {652653private int typeval;654655MTLSwToTextureBlit(SurfaceType srcType, int typeval) {656super(srcType,657CompositeType.SrcNoEa,658MTLSurfaceData.MTLTexture);659this.typeval = typeval;660}661662public void Blit(SurfaceData src, SurfaceData dst,663Composite comp, Region clip,664int sx, int sy, int dx, int dy, int w, int h)665{666MTLBlitLoops.Blit(src, dst,667comp, clip, null,668AffineTransformOp.TYPE_NEAREST_NEIGHBOR,669sx, sy, sx+w, sy+h,670dx, dy, dx+w, dy+h,671typeval, true);672}673}674675class MTLTextureToSurfaceBlit extends Blit {676677MTLTextureToSurfaceBlit() {678super(MTLSurfaceData.MTLTexture,679CompositeType.AnyAlpha,680MTLSurfaceData.MTLSurface);681}682683public void Blit(SurfaceData src, SurfaceData dst,684Composite comp, Region clip,685int sx, int sy, int dx, int dy, int w, int h)686{687MTLBlitLoops.IsoBlit(src, dst,688null, null,689comp, clip, null,690AffineTransformOp.TYPE_NEAREST_NEIGHBOR,691sx, sy, sx+w, sy+h,692dx, dy, dx+w, dy+h,693true);694}695}696697class MTLTextureToSurfaceScale extends ScaledBlit {698699MTLTextureToSurfaceScale() {700super(MTLSurfaceData.MTLTexture,701CompositeType.AnyAlpha,702MTLSurfaceData.MTLSurface);703}704705public void Scale(SurfaceData src, SurfaceData dst,706Composite comp, Region clip,707int sx1, int sy1,708int sx2, int sy2,709double dx1, double dy1,710double dx2, double dy2)711{712MTLBlitLoops.IsoBlit(src, dst,713null, null,714comp, clip, null,715AffineTransformOp.TYPE_NEAREST_NEIGHBOR,716sx1, sy1, sx2, sy2,717dx1, dy1, dx2, dy2,718true);719}720}721722class MTLTextureToSurfaceTransform extends TransformBlit {723724MTLTextureToSurfaceTransform() {725super(MTLSurfaceData.MTLTexture,726CompositeType.AnyAlpha,727MTLSurfaceData.MTLSurface);728}729730public void Transform(SurfaceData src, SurfaceData dst,731Composite comp, Region clip,732AffineTransform at, int hint,733int sx, int sy, int dx, int dy,734int w, int h)735{736MTLBlitLoops.IsoBlit(src, dst,737null, null,738comp, clip, at, hint,739sx, sy, sx+w, sy+h,740dx, dy, dx+w, dy+h,741true);742}743}744745/**746* This general Blit implementation converts any source surface to an747* intermediate IntArgbPre surface, and then uses the more specific748* IntArgbPre->MTLSurface/Texture loop to get the intermediate749* (premultiplied) surface down to Metal using simple blit.750*/751class MTLGeneralBlit extends Blit {752753private final Blit performop;754private WeakReference<SurfaceData> srcTmp;755756MTLGeneralBlit(SurfaceType dstType,757CompositeType compType,758Blit performop)759{760super(SurfaceType.Any, compType, dstType);761this.performop = performop;762}763764public synchronized void Blit(SurfaceData src, SurfaceData dst,765Composite comp, Region clip,766int sx, int sy, int dx, int dy,767int w, int h)768{769Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),770CompositeType.SrcNoEa,771SurfaceType.IntArgbPre);772773SurfaceData cachedSrc = null;774if (srcTmp != null) {775// use cached intermediate surface, if available776cachedSrc = srcTmp.get();777}778779// convert source to IntArgbPre780src = convertFrom(convertsrc, src, sx, sy, w, h,781cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);782783// copy IntArgbPre intermediate surface to Metal surface784performop.Blit(src, dst, comp, clip,7850, 0, dx, dy, w, h);786787if (src != cachedSrc) {788// cache the intermediate surface789srcTmp = new WeakReference<>(src);790}791}792}793794/**795* This general TransformedBlit implementation converts any source surface to an796* intermediate IntArgbPre surface, and then uses the more specific797* IntArgbPre->MTLSurface/Texture loop to get the intermediate798* (premultiplied) surface down to Metal using simple transformBlit.799*/800final class MTLGeneralTransformedBlit extends TransformBlit {801802private final TransformBlit performop;803private WeakReference<SurfaceData> srcTmp;804805MTLGeneralTransformedBlit(final TransformBlit performop) {806super(SurfaceType.Any, CompositeType.AnyAlpha,807MTLSurfaceData.MTLSurface);808this.performop = performop;809}810811@Override812public synchronized void Transform(SurfaceData src, SurfaceData dst,813Composite comp, Region clip,814AffineTransform at, int hint, int srcx,815int srcy, int dstx, int dsty, int width,816int height){817Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),818CompositeType.SrcNoEa,819SurfaceType.IntArgbPre);820// use cached intermediate surface, if available821final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;822// convert source to IntArgbPre823src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,824BufferedImage.TYPE_INT_ARGB_PRE);825826// transform IntArgbPre intermediate surface to Metal surface827performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,828width, height);829830if (src != cachedSrc) {831// cache the intermediate surface832srcTmp = new WeakReference<>(src);833}834}835}836837/**838* This general MTLAnyCompositeBlit implementation can convert any source/target839* surface to an intermediate surface using convertsrc/convertdst loops, applies840* necessary composite operation, and then uses convertresult loop to get the841* intermediate surface down to Metal.842*/843final class MTLAnyCompositeBlit extends Blit {844845private WeakReference<SurfaceData> dstTmp;846private WeakReference<SurfaceData> srcTmp;847private final Blit convertsrc;848private final Blit convertdst;849private final Blit convertresult;850851MTLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,852Blit convertresult) {853super(srctype, CompositeType.Any, MTLSurfaceData.MTLSurface);854this.convertsrc = convertsrc;855this.convertdst = convertdst;856this.convertresult = convertresult;857}858859public synchronized void Blit(SurfaceData src, SurfaceData dst,860Composite comp, Region clip,861int sx, int sy, int dx, int dy,862int w, int h)863{864if (convertsrc != null) {865SurfaceData cachedSrc = null;866if (srcTmp != null) {867// use cached intermediate surface, if available868cachedSrc = srcTmp.get();869}870// convert source to IntArgbPre871src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc,872BufferedImage.TYPE_INT_ARGB_PRE);873if (src != cachedSrc) {874// cache the intermediate surface875srcTmp = new WeakReference<>(src);876}877}878879SurfaceData cachedDst = null;880881if (dstTmp != null) {882// use cached intermediate surface, if available883cachedDst = dstTmp.get();884}885886// convert destination to IntArgbPre887SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,888cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);889Region bufferClip =890clip == null ? null : clip.getTranslatedRegion(-dx, -dy);891892Blit performop = Blit.getFromCache(src.getSurfaceType(),893CompositeType.Any, dstBuffer.getSurfaceType());894performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h);895896if (dstBuffer != cachedDst) {897// cache the intermediate surface898dstTmp = new WeakReference<>(dstBuffer);899}900// now blit the buffer back to the destination901convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx,902dy, w, h);903}904}905906907