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 #import "MTLGraphicsConfig.h" 27 #import "MTLLayer.h" 28 #import "ThreadUtilities.h" 29 #import "LWCToolkit.h" 30 #import "MTLSurfaceData.h" 31 32 #import "MTLBlitLoops.h" 33 34 @implementation MTLLayer 35 36 37 @synthesize javaLayer; 38 @synthesize ctx; 39 @synthesize bufferWidth; 40 @synthesize bufferHeight; 41 @synthesize buffer; 42 43 - (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer 44 { 45 AWT_ASSERT_APPKIT_THREAD; 46 // Initialize ourselves 47 self = [super init]; 48 if (self == nil) return self; 49 50 self.javaLayer = layer; 51 52 self.contentsGravity = kCAGravityTopLeft; 53 54 //Disable CALayer's default animation 55 NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys: 56 [NSNull null], @"anchorPoint", 57 [NSNull null], @"bounds", 58 [NSNull null], @"contents", 59 [NSNull null], @"contentsScale", 60 [NSNull null], @"onOrderIn", 61 [NSNull null], @"onOrderOut", 62 [NSNull null], @"position", 63 [NSNull null], @"sublayers", 64 nil]; 65 self.actions = actions; 66 [actions release]; 67 68 69 return self; 70 } 71 72 - (void) blitTexture:(id<MTLCommandBuffer>)commandBuf { 73 if (self.ctx == NULL || self.javaLayer == NULL || self.buffer == nil || ctx.device == nil) { 74 J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, devide=%p)", self.ctx, self.javaLayer, self.buffer, ctx.device); 75 return; 76 } 77 78 if (commandBuf == nil) { 79 J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nothing to do (commandBuf is null)"); 80 return; 81 } 82 83 @autoreleasepool { 84 self.device = ctx.device; 85 self.pixelFormat = MTLPixelFormatBGRA8Unorm; 86 self.framebufferOnly = NO; 87 88 self.drawableSize = 89 CGSizeMake(self.buffer.width, 90 self.buffer.height); 91 92 id<CAMetalDrawable> mtlDrawable = [self nextDrawable]; 93 if (mtlDrawable == nil) { 94 return; 95 } 96 J2dTraceLn6(J2D_TRACE_INFO, "MTLLayer.blitTexture: src tex=%p (w=%d, h=%d), dst tex=%p (w=%d, h=%d)", self.buffer, self.buffer.width, self.buffer.height, mtlDrawable.texture, mtlDrawable.texture.width, mtlDrawable.texture.height); 97 id <MTLBlitCommandEncoder> blitEncoder = [commandBuf blitCommandEncoder]; 98 [blitEncoder 99 copyFromTexture:self.buffer sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(0, 0, 0) sourceSize:MTLSizeMake(self.buffer.width, self.buffer.height, 1) 100 toTexture:mtlDrawable.texture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)]; 101 [blitEncoder endEncoding]; 102 103 [commandBuf presentDrawable:mtlDrawable]; 104 105 [commandBuf addCompletedHandler:^(id <MTLCommandBuffer> cmdBuff) { 106 [cmdBuff release]; 107 [ctx.texturePool markAllTexturesFree]; 108 }]; 109 110 [commandBuf commit]; 111 } 112 } 113 114 - (void) dealloc { 115 self.javaLayer = nil; 116 [super dealloc]; 117 } 118 119 @end 120 121 /* 122 * Class: sun_java2d_metal_CGLLayer 123 * Method: nativeCreateLayer 124 * Signature: ()J 125 */ 126 JNIEXPORT jlong JNICALL 127 Java_sun_java2d_metal_MTLLayer_nativeCreateLayer 128 (JNIEnv *env, jobject obj) 129 { 130 __block MTLLayer *layer = nil; 131 132 JNF_COCOA_ENTER(env); 133 134 JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env]; 135 136 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 137 AWT_ASSERT_APPKIT_THREAD; 138 139 layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer]; 140 }]; 141 142 JNF_COCOA_EXIT(env); 143 144 return ptr_to_jlong(layer); 145 } 146 147 // Must be called under the RQ lock. 148 JNIEXPORT void JNICALL 149 Java_sun_java2d_metal_MTLLayer_validate 150 (JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData) 151 { 152 MTLLayer *layer = OBJC(layerPtr); 153 154 if (surfaceData != NULL) { 155 BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData); 156 layer.bufferWidth = bmtlsdo->width; 157 layer.bufferHeight = bmtlsdo->width; 158 layer.buffer = bmtlsdo->pTexture; 159 layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context; 160 layer.device = layer.ctx.device; 161 } else { 162 layer.ctx = NULL; 163 } 164 } 165 166 JNIEXPORT void JNICALL 167 Java_sun_java2d_metal_MTLLayer_nativeSetScale 168 (JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale) 169 { 170 JNF_COCOA_ENTER(env); 171 MTLLayer *layer = jlong_to_ptr(layerPtr); 172 // We always call all setXX methods asynchronously, exception is only in 173 // this method where we need to change native texture size and layer's scale 174 // in one call on appkit, otherwise we'll get window's contents blinking, 175 // during screen-2-screen moving. 176 [ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){ 177 layer.contentsScale = scale; 178 }]; 179 JNF_COCOA_EXIT(env); 180 }