Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m
66646 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*/2425#import "MTLGraphicsConfig.h"26#import "MTLLayer.h"27#import "ThreadUtilities.h"28#import "LWCToolkit.h"29#import "MTLSurfaceData.h"30#import "JNIUtilities.h"3132@implementation MTLLayer333435@synthesize javaLayer;36@synthesize ctx;37@synthesize bufferWidth;38@synthesize bufferHeight;39@synthesize buffer;40@synthesize topInset;41@synthesize leftInset;42@synthesize nextDrawableCount;43@synthesize displayLink;4445- (id) initWithJavaLayer:(jobject)layer46{47AWT_ASSERT_APPKIT_THREAD;48// Initialize ourselves49self = [super init];50if (self == nil) return self;5152self.javaLayer = layer;5354self.contentsGravity = kCAGravityTopLeft;5556//Disable CALayer's default animation57NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:58[NSNull null], @"anchorPoint",59[NSNull null], @"bounds",60[NSNull null], @"contents",61[NSNull null], @"contentsScale",62[NSNull null], @"onOrderIn",63[NSNull null], @"onOrderOut",64[NSNull null], @"position",65[NSNull null], @"sublayers",66nil];67self.actions = actions;68[actions release];69self.topInset = 0;70self.leftInset = 0;71self.framebufferOnly = NO;72self.nextDrawableCount = 0;73self.opaque = FALSE;74CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);75CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void*)self);76return self;77}7879- (void) blitTexture {80if (self.ctx == NULL || self.javaLayer == NULL || self.buffer == nil || self.ctx.device == nil) {81J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, devide=%p)", self.ctx, self.javaLayer, self.buffer, ctx.device);82[self stopDisplayLink];83return;84}8586if (self.nextDrawableCount != 0) {87return;88}89@autoreleasepool {90if ((self.buffer.width == 0) || (self.buffer.height == 0)) {91J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: cannot create drawable of size 0");92[self stopDisplayLink];93return;94}9596NSUInteger src_x = self.leftInset * self.contentsScale;97NSUInteger src_y = self.topInset * self.contentsScale;98NSUInteger src_w = self.buffer.width - src_x;99NSUInteger src_h = self.buffer.height - src_y;100101if (src_h <= 0 || src_w <= 0) {102J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: Invalid src width or height.");103[self stopDisplayLink];104return;105}106107id<MTLCommandBuffer> commandBuf = [self.ctx createBlitCommandBuffer];108if (commandBuf == nil) {109J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: commandBuf is null");110[self stopDisplayLink];111return;112}113id<CAMetalDrawable> mtlDrawable = [self nextDrawable];114if (mtlDrawable == nil) {115J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nextDrawable is null)");116[self stopDisplayLink];117return;118}119self.nextDrawableCount++;120121id <MTLBlitCommandEncoder> blitEncoder = [commandBuf blitCommandEncoder];122123[blitEncoder124copyFromTexture:self.buffer sourceSlice:0 sourceLevel:0125sourceOrigin:MTLOriginMake(src_x, src_y, 0)126sourceSize:MTLSizeMake(src_w, src_h, 1)127toTexture:mtlDrawable.texture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)];128[blitEncoder endEncoding];129130[commandBuf presentDrawable:mtlDrawable];131[commandBuf addCompletedHandler:^(id <MTLCommandBuffer> commandBuf) {132self.nextDrawableCount--;133}];134135[commandBuf commit];136[self stopDisplayLink];137}138}139140- (void) dealloc {141JNIEnv *env = [ThreadUtilities getJNIEnvUncached];142(*env)->DeleteWeakGlobalRef(env, self.javaLayer);143self.javaLayer = nil;144[self stopDisplayLink];145CVDisplayLinkRelease(self.displayLink);146self.displayLink = nil;147[super dealloc];148}149150- (void) blitCallback {151152JNIEnv *env = [ThreadUtilities getJNIEnv];153DECLARE_CLASS(jc_JavaLayer, "sun/java2d/metal/MTLLayer");154DECLARE_METHOD(jm_drawInMTLContext, jc_JavaLayer, "drawInMTLContext", "()V");155156jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);157if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {158return;159}160161(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInMTLContext);162CHECK_EXCEPTION();163(*env)->DeleteLocalRef(env, javaLayerLocalRef);164}165166- (void) display {167AWT_ASSERT_APPKIT_THREAD;168J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_display() called");169[self blitCallback];170[super display];171}172173- (void) redraw {174AWT_ASSERT_APPKIT_THREAD;175[self setNeedsDisplay];176}177178- (void) startDisplayLink {179if (!CVDisplayLinkIsRunning(self.displayLink))180CVDisplayLinkStart(self.displayLink);181}182183- (void) stopDisplayLink {184if (CVDisplayLinkIsRunning(self.displayLink))185CVDisplayLinkStop(self.displayLink);186}187188CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)189{190J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_displayLinkCallback() called");191@autoreleasepool {192MTLLayer *layer = (__bridge MTLLayer *)displayLinkContext;193[layer performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:NO];194}195return kCVReturnSuccess;196}197@end198199/*200* Class: sun_java2d_metal_MTLLayer201* Method: nativeCreateLayer202* Signature: ()J203*/204JNIEXPORT jlong JNICALL205Java_sun_java2d_metal_MTLLayer_nativeCreateLayer206(JNIEnv *env, jobject obj)207{208__block MTLLayer *layer = nil;209210JNI_COCOA_ENTER(env);211212jobject javaLayer = (*env)->NewWeakGlobalRef(env, obj);213214[ThreadUtilities performOnMainThreadWaiting:YES block:^(){215AWT_ASSERT_APPKIT_THREAD;216217layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer];218}];219220JNI_COCOA_EXIT(env);221222return ptr_to_jlong(layer);223}224225// Must be called under the RQ lock.226JNIEXPORT void JNICALL227Java_sun_java2d_metal_MTLLayer_validate228(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)229{230MTLLayer *layer = OBJC(layerPtr);231232if (surfaceData != NULL) {233BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData);234layer.bufferWidth = bmtlsdo->width;235layer.bufferHeight = bmtlsdo->width;236layer.buffer = bmtlsdo->pTexture;237layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context;238layer.device = layer.ctx.device;239layer.pixelFormat = MTLPixelFormatBGRA8Unorm;240layer.drawableSize =241CGSizeMake(layer.buffer.width,242layer.buffer.height);243[layer startDisplayLink];244} else {245layer.ctx = NULL;246[layer stopDisplayLink];247}248}249250JNIEXPORT void JNICALL251Java_sun_java2d_metal_MTLLayer_nativeSetScale252(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)253{254JNI_COCOA_ENTER(env);255MTLLayer *layer = jlong_to_ptr(layerPtr);256// We always call all setXX methods asynchronously, exception is only in257// this method where we need to change native texture size and layer's scale258// in one call on appkit, otherwise we'll get window's contents blinking,259// during screen-2-screen moving.260[ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){261layer.contentsScale = scale;262}];263JNI_COCOA_EXIT(env);264}265266JNIEXPORT void JNICALL267Java_sun_java2d_metal_MTLLayer_nativeSetInsets268(JNIEnv *env, jclass cls, jlong layerPtr, jint top, jint left)269{270MTLLayer *layer = jlong_to_ptr(layerPtr);271layer.topInset = top;272layer.leftInset = left;273}274275JNIEXPORT void JNICALL276Java_sun_java2d_metal_MTLLayer_blitTexture277(JNIEnv *env, jclass cls, jlong layerPtr)278{279J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blitTexture");280MTLLayer *layer = jlong_to_ptr(layerPtr);281MTLContext * ctx = layer.ctx;282if (layer == NULL || ctx == NULL) {283J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blit : Layer or Context is null");284[layer stopDisplayLink];285return;286}287288[layer blitTexture];289}290291292