Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m
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*/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);82return;83}8485if (self.nextDrawableCount != 0) {86return;87}88@autoreleasepool {89if ((self.buffer.width == 0) || (self.buffer.height == 0)) {90J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: cannot create drawable of size 0");91return;92}9394NSUInteger src_x = self.leftInset * self.contentsScale;95NSUInteger src_y = self.topInset * self.contentsScale;96NSUInteger src_w = self.buffer.width - src_x;97NSUInteger src_h = self.buffer.height - src_y;9899if (src_h <= 0 || src_w <= 0) {100J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: Invalid src width or height.");101return;102}103104id<MTLCommandBuffer> commandBuf = [self.ctx createBlitCommandBuffer];105if (commandBuf == nil) {106J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: commandBuf is null");107return;108}109id<CAMetalDrawable> mtlDrawable = [self nextDrawable];110if (mtlDrawable == nil) {111J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nextDrawable is null)");112return;113}114self.nextDrawableCount++;115116id <MTLBlitCommandEncoder> blitEncoder = [commandBuf blitCommandEncoder];117118[blitEncoder119copyFromTexture:self.buffer sourceSlice:0 sourceLevel:0120sourceOrigin:MTLOriginMake(src_x, src_y, 0)121sourceSize:MTLSizeMake(src_w, src_h, 1)122toTexture:mtlDrawable.texture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)];123[blitEncoder endEncoding];124125[commandBuf presentDrawable:mtlDrawable];126[commandBuf addCompletedHandler:^(id <MTLCommandBuffer> commandBuf) {127self.nextDrawableCount--;128}];129130[commandBuf commit];131[self stopDisplayLink];132}133}134135- (void) dealloc {136JNIEnv *env = [ThreadUtilities getJNIEnvUncached];137(*env)->DeleteWeakGlobalRef(env, self.javaLayer);138self.javaLayer = nil;139[self stopDisplayLink];140CVDisplayLinkRelease(self.displayLink);141self.displayLink = nil;142[super dealloc];143}144145- (void) blitCallback {146147JNIEnv *env = [ThreadUtilities getJNIEnv];148DECLARE_CLASS(jc_JavaLayer, "sun/java2d/metal/MTLLayer");149DECLARE_METHOD(jm_drawInMTLContext, jc_JavaLayer, "drawInMTLContext", "()V");150151jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);152if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {153return;154}155156(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInMTLContext);157CHECK_EXCEPTION();158(*env)->DeleteLocalRef(env, javaLayerLocalRef);159}160161- (void) display {162AWT_ASSERT_APPKIT_THREAD;163J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_display() called");164[self blitCallback];165[super display];166}167168- (void) redraw {169AWT_ASSERT_APPKIT_THREAD;170[self setNeedsDisplay];171}172173- (void) startDisplayLink {174if (!CVDisplayLinkIsRunning(self.displayLink))175CVDisplayLinkStart(self.displayLink);176}177178- (void) stopDisplayLink {179if (CVDisplayLinkIsRunning(self.displayLink))180CVDisplayLinkStop(self.displayLink);181}182183CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)184{185J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_displayLinkCallback() called");186@autoreleasepool {187MTLLayer *layer = (__bridge MTLLayer *)displayLinkContext;188[layer performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:NO];189}190return kCVReturnSuccess;191}192@end193194/*195* Class: sun_java2d_metal_MTLLayer196* Method: nativeCreateLayer197* Signature: ()J198*/199JNIEXPORT jlong JNICALL200Java_sun_java2d_metal_MTLLayer_nativeCreateLayer201(JNIEnv *env, jobject obj)202{203__block MTLLayer *layer = nil;204205JNI_COCOA_ENTER(env);206207jobject javaLayer = (*env)->NewWeakGlobalRef(env, obj);208209[ThreadUtilities performOnMainThreadWaiting:YES block:^(){210AWT_ASSERT_APPKIT_THREAD;211212layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer];213}];214215JNI_COCOA_EXIT(env);216217return ptr_to_jlong(layer);218}219220// Must be called under the RQ lock.221JNIEXPORT void JNICALL222Java_sun_java2d_metal_MTLLayer_validate223(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)224{225MTLLayer *layer = OBJC(layerPtr);226227if (surfaceData != NULL) {228BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData);229layer.bufferWidth = bmtlsdo->width;230layer.bufferHeight = bmtlsdo->width;231layer.buffer = bmtlsdo->pTexture;232layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context;233layer.device = layer.ctx.device;234layer.pixelFormat = MTLPixelFormatBGRA8Unorm;235layer.drawableSize =236CGSizeMake(layer.buffer.width,237layer.buffer.height);238[layer startDisplayLink];239} else {240layer.ctx = NULL;241[layer stopDisplayLink];242}243}244245JNIEXPORT void JNICALL246Java_sun_java2d_metal_MTLLayer_nativeSetScale247(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)248{249JNI_COCOA_ENTER(env);250MTLLayer *layer = jlong_to_ptr(layerPtr);251// We always call all setXX methods asynchronously, exception is only in252// this method where we need to change native texture size and layer's scale253// in one call on appkit, otherwise we'll get window's contents blinking,254// during screen-2-screen moving.255[ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){256layer.contentsScale = scale;257}];258JNI_COCOA_EXIT(env);259}260261JNIEXPORT void JNICALL262Java_sun_java2d_metal_MTLLayer_nativeSetInsets263(JNIEnv *env, jclass cls, jlong layerPtr, jint top, jint left)264{265MTLLayer *layer = jlong_to_ptr(layerPtr);266layer.topInset = top;267layer.leftInset = left;268}269270JNIEXPORT void JNICALL271Java_sun_java2d_metal_MTLLayer_blitTexture272(JNIEnv *env, jclass cls, jlong layerPtr)273{274J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blitTexture");275MTLLayer *layer = jlong_to_ptr(layerPtr);276MTLContext * ctx = layer.ctx;277if (layer == NULL || ctx == NULL) {278J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blit : Layer or Context is null");279return;280}281282[layer blitTexture];283}284285286