Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m
41159 views
/*1* Copyright (c) 2011, 2019, 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 "CGLGraphicsConfig.h"26#import "CGLLayer.h"27#import "ThreadUtilities.h"28#import "LWCToolkit.h"29#import "CGLSurfaceData.h"30#import "JNIUtilities.h"313233extern NSOpenGLPixelFormat *sharedPixelFormat;34extern NSOpenGLContext *sharedContext;3536@implementation CGLLayer3738@synthesize javaLayer;39@synthesize textureID;40@synthesize target;41@synthesize textureWidth;42@synthesize textureHeight;4344- (id) initWithJavaLayer:(jobject)layer;45{46AWT_ASSERT_APPKIT_THREAD;47// Initialize ourselves48self = [super init];49if (self == nil) return self;5051self.javaLayer = layer;5253// NOTE: async=YES means that the layer is re-cached periodically54self.asynchronous = FALSE;55self.contentsGravity = kCAGravityTopLeft;56//Layer backed view57//self.needsDisplayOnBoundsChange = YES;58//self.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;5960//Disable CALayer's default animation61NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:62[NSNull null], @"anchorPoint",63[NSNull null], @"bounds",64[NSNull null], @"contents",65[NSNull null], @"contentsScale",66[NSNull null], @"onOrderIn",67[NSNull null], @"onOrderOut",68[NSNull null], @"position",69[NSNull null], @"sublayers",70nil];71self.actions = actions;72[actions release];7374textureID = 0; // texture will be created by rendering pipe75target = 0;7677return self;78}7980- (void) dealloc {81JNIEnv *env = [ThreadUtilities getJNIEnvUncached];82(*env)->DeleteWeakGlobalRef(env, self.javaLayer);83self.javaLayer = nil;84[super dealloc];85}8687- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {88return CGLRetainPixelFormat(sharedPixelFormat.CGLPixelFormatObj);89}9091- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {92CGLContextObj contextObj = NULL;93CGLCreateContext(pixelFormat, sharedContext.CGLContextObj, &contextObj);94return contextObj;95}9697// use texture (intermediate buffer) as src and blit it to the layer98- (void) blitTexture99{100if (textureID == 0) {101return;102}103104glEnable(target);105glBindTexture(target, textureID);106107glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // srccopy108109float swid = 1.0f, shgt = 1.0f;110if (target == GL_TEXTURE_RECTANGLE_ARB) {111swid = textureWidth;112shgt = textureHeight;113}114glBegin(GL_QUADS);115glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);116glTexCoord2f(swid, 0.0f); glVertex2f( 1.0f, -1.0f);117glTexCoord2f(swid, shgt); glVertex2f( 1.0f, 1.0f);118glTexCoord2f(0.0f, shgt); glVertex2f(-1.0f, 1.0f);119glEnd();120121glBindTexture(target, 0);122glDisable(target);123}124125-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{126return textureID == 0 ? NO : YES;127}128129-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp130{131AWT_ASSERT_APPKIT_THREAD;132133JNIEnv *env = [ThreadUtilities getJNIEnv];134DECLARE_CLASS(jc_JavaLayer, "sun/java2d/opengl/CGLLayer");135DECLARE_METHOD(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V");136137jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);138if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {139return;140}141142// Set the current context to the one given to us.143CGLSetCurrentContext(glContext);144145// Should clear the whole CALayer, because it can be larger than our texture.146glClearColor(0.0, 0.0, 0.0, 0.0);147glClear(GL_COLOR_BUFFER_BIT);148149glViewport(0, 0, textureWidth, textureHeight);150151(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInCGLContext);152CHECK_EXCEPTION();153(*env)->DeleteLocalRef(env, javaLayerLocalRef);154155// Call super to finalize the drawing. By default all it does is call glFlush().156[super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];157158CGLSetCurrentContext(NULL);159}160161@end162163/*164* Class: sun_java2d_opengl_CGLLayer165* Method: nativeCreateLayer166* Signature: ()J167*/168JNIEXPORT jlong JNICALL169Java_sun_java2d_opengl_CGLLayer_nativeCreateLayer170(JNIEnv *env, jobject obj)171{172__block CGLLayer *layer = nil;173174JNI_COCOA_ENTER(env);175176jobject javaLayer = (*env)->NewWeakGlobalRef(env, obj);177178[ThreadUtilities performOnMainThreadWaiting:YES block:^(){179AWT_ASSERT_APPKIT_THREAD;180181layer = [[CGLLayer alloc] initWithJavaLayer: javaLayer];182}];183184JNI_COCOA_EXIT(env);185186return ptr_to_jlong(layer);187}188189// Must be called under the RQ lock.190JNIEXPORT void JNICALL191Java_sun_java2d_opengl_CGLLayer_validate192(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)193{194CGLLayer *layer = OBJC(layerPtr);195196if (surfaceData != NULL) {197OGLSDOps *oglsdo = (OGLSDOps*) SurfaceData_GetOps(env, surfaceData);198layer.textureID = oglsdo->textureID;199layer.target = GL_TEXTURE_2D;200layer.textureWidth = oglsdo->width;201layer.textureHeight = oglsdo->height;202} else {203layer.textureID = 0;204}205}206207// Must be called on the AppKit thread and under the RQ lock.208JNIEXPORT void JNICALL209Java_sun_java2d_opengl_CGLLayer_blitTexture210(JNIEnv *env, jclass cls, jlong layerPtr)211{212CGLLayer *layer = jlong_to_ptr(layerPtr);213214[layer blitTexture];215}216217JNIEXPORT void JNICALL218Java_sun_java2d_opengl_CGLLayer_nativeSetScale219(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)220{221JNI_COCOA_ENTER(env);222CGLLayer *layer = jlong_to_ptr(layerPtr);223// We always call all setXX methods asynchronously, exception is only in224// this method where we need to change native texture size and layer's scale225// in one call on appkit, otherwise we'll get window's contents blinking,226// during screen-2-screen moving.227[ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){228layer.contentsScale = scale;229}];230JNI_COCOA_EXIT(env);231}232233234