--- /dev/null 2019-03-05 14:31:15.000000000 +0300 +++ new/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m 2019-03-05 14:31:15.000000000 +0300 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#import "MTLGraphicsConfig.h" +#import "MTLLayer.h" +#import "ThreadUtilities.h" +#import "LWCToolkit.h" +#import "MTLSurfaceData.h" + + +@implementation MTLLayer + + +@synthesize javaLayer; +@synthesize ctx; +@synthesize bufferWidth; +@synthesize bufferHeight; + +- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer +{ + AWT_ASSERT_APPKIT_THREAD; + // Initialize ourselves + self = [super init]; + if (self == nil) return self; + + self.javaLayer = layer; + + self.contentsGravity = kCAGravityTopLeft; + + //Disable CALayer's default animation + NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + [NSNull null], @"anchorPoint", + [NSNull null], @"bounds", + [NSNull null], @"contents", + [NSNull null], @"contentsScale", + [NSNull null], @"onOrderIn", + [NSNull null], @"onOrderOut", + [NSNull null], @"position", + [NSNull null], @"sublayers", + nil]; + self.actions = actions; + [actions release]; + + + return self; +} + +- (void) blitTexture { + if (self.ctx == NULL || self.javaLayer == NULL) { + return; + } + + @autoreleasepool { + if (ctx->mtlCommandBuffer && ctx->mtlDevice) { + self.device = ctx->mtlDevice; + self.pixelFormat = MTLPixelFormatBGRA8Unorm; + self.framebufferOnly = NO; + + self.drawableSize = + CGSizeMake(ctx->mtlFrameBuffer.width, + ctx->mtlFrameBuffer.height); + + id mtlDrawable = [self nextDrawable]; + if (mtlDrawable == nil) { + [ctx->mtlCommandBuffer release]; + ctx->mtlCommandBuffer = nil; + ctx->mtlEmptyCommandBuffer = YES; + if (ctx->mtlRenderPassDesc) { + [ctx->mtlRenderPassDesc release]; + ctx->mtlRenderPassDesc = nil; + } + return; + } + + if (!ctx->mtlRenderPassDesc) { + ctx->mtlRenderPassDesc = [[MTLRenderPassDescriptor renderPassDescriptor] retain]; + } + MTLRenderPassColorAttachmentDescriptor *colorAttachment = ctx->mtlRenderPassDesc.colorAttachments[0]; + + colorAttachment.texture = mtlDrawable.texture; + + colorAttachment.loadAction = MTLLoadActionLoad; + colorAttachment.clearColor = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f); + + colorAttachment.storeAction = MTLStoreActionStore; + + id mtlEncoder = + [ctx->mtlCommandBuffer renderCommandEncoderWithDescriptor:ctx->mtlRenderPassDesc]; + MTLViewport vp = {0, 0, ctx->mtlFrameBuffer.width, ctx->mtlFrameBuffer.height, 0, 1}; + + [mtlEncoder setViewport:vp]; + [mtlEncoder setRenderPipelineState:ctx->mtlBlitPipelineState]; + [mtlEncoder setFragmentTexture: ctx->mtlFrameBuffer atIndex: 0]; + [mtlEncoder setVertexBuffer:ctx->mtlVertexBuffer offset:0 atIndex:MeshVertexBuffer]; + [mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:PGRAM_VERTEX_COUNT]; + [mtlEncoder endEncoding]; + + + if (!ctx->mtlEmptyCommandBuffer) { + [ctx->mtlCommandBuffer presentDrawable:mtlDrawable]; + [ctx->mtlCommandBuffer commit]; + } + + [ctx->mtlRenderPassDesc release]; + ctx->mtlRenderPassDesc = nil; + + [ctx->mtlCommandBuffer release]; + ctx->mtlCommandBuffer = nil; + ctx->mtlEmptyCommandBuffer = YES; + } + } +} + +- (void) dealloc { + self.javaLayer = nil; + [super dealloc]; +} + +@end + +/* + * Class: sun_java2d_metal_CGLLayer + * Method: nativeCreateLayer + * Signature: ()J + */ +JNIEXPORT jlong JNICALL +Java_sun_java2d_metal_MTLLayer_nativeCreateLayer +(JNIEnv *env, jobject obj) +{ + __block MTLLayer *layer = nil; + +JNF_COCOA_ENTER(env); + + JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env]; + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer]; + }]; + +JNF_COCOA_EXIT(env); + + return ptr_to_jlong(layer); +} + +// Must be called under the RQ lock. +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLLayer_validate +(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData) +{ + MTLLayer *layer = OBJC(layerPtr); + + if (surfaceData != NULL) { + BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData); + layer.bufferWidth = bmtlsdo->width; + layer.bufferHeight = bmtlsdo->height; + layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context; + layer.device = layer.ctx->mtlDevice; + } else { + layer.ctx = NULL; + } +} + +// Must be called on the AppKit thread and under the RQ lock. +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLLayer_blitTexture +(JNIEnv *env, jclass cls, jlong layerPtr) +{ + MTLLayer *layer = jlong_to_ptr(layerPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + [layer blitTexture]; + }]; +} + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLLayer_nativeSetScale +(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale) +{ + JNF_COCOA_ENTER(env); + MTLLayer *layer = jlong_to_ptr(layerPtr); + // We always call all setXX methods asynchronously, exception is only in + // this method where we need to change native texture size and layer's scale + // in one call on appkit, otherwise we'll get window's contents blinking, + // during screen-2-screen moving. + [ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){ + layer.contentsScale = scale; + }]; + JNF_COCOA_EXIT(env); +}