From e1d24ec06516ecb3af130809b4e63263b139a66a Mon Sep 17 00:00:00 2001 From: Graham Date: Sat, 7 Sep 2019 15:24:49 +0100 Subject: [PATCH] Add legacy NSView support NSView is used in preference to CALayer if available, as we avoid all the framebuffer blitting overhead. --- gl-natives/src/main/c/jaggl.c | 122 ++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/gl-natives/src/main/c/jaggl.c b/gl-natives/src/main/c/jaggl.c index e630b935be..230d502d32 100644 --- a/gl-natives/src/main/c/jaggl.c +++ b/gl-natives/src/main/c/jaggl.c @@ -27,14 +27,18 @@ #include #if defined(__APPLE__) && defined(__MACH__) -#define _JAGGL_JAWT_VERSION (JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER) +#define _JAGGL_GET(env) \ + JAWT awt = { .version = JAWT_VERSION_1_4 }; \ + bool awt_valid = JAWT_GetAWT(env, &awt); \ + if (!awt_valid) { \ + awt.version |= JAWT_MACOSX_USE_CALAYER; \ + awt_valid = JAWT_GetAWT(env, &awt); \ + } #else -#define _JAGGL_JAWT_VERSION JAWT_VERSION_1_4 -#endif - #define _JAGGL_GET(env) \ - JAWT awt = { .version = (jint) _JAGGL_JAWT_VERSION }; \ + JAWT awt = { .version = JAWT_VERSION_1_4 }; \ bool awt_valid = JAWT_GetAWT(env, &awt); +#endif #define _JAGGL_GET_AND_LOCK(env) \ _JAGGL_GET(env); \ @@ -126,6 +130,11 @@ static HWND jaggl_window; static HDC jaggl_device; static HGLRC jaggl_context; #elif defined(__APPLE__) && defined(__MACH__) +/* copy of JAWT_MacOSXDrawingSurfaceInfo from Java 6's jawt_md.h */ +struct jaggl_legacy_dsi { + NSView *view; +}; + @interface JagGLLayer : CAOpenGLLayer { @private @@ -136,6 +145,7 @@ static HGLRC jaggl_context; } @end +static bool jaggl_calayer; static CGLContextObj jaggl_onscreen_context; static CGLContextObj jaggl_context; static CGLPixelFormatObj jaggl_pix; @@ -697,24 +707,26 @@ JNIEXPORT jboolean JNICALL Java_jaggl_context_destroy(JNIEnv *env, jclass cls) { jaggl_context_appkit = NULL; } - if (jaggl_view) { - [jaggl_view release]; - jaggl_view = NULL; - } + if (jaggl_calayer) { + if (jaggl_view) { + [jaggl_view release]; + jaggl_view = NULL; + } - if (jaggl_window) { - [jaggl_window release]; - jaggl_window = NULL; - } + if (jaggl_window) { + [jaggl_window release]; + jaggl_window = NULL; + } - if (jaggl_layer) { - [jaggl_layer removeFromSuperlayer]; - [jaggl_layer release]; - jaggl_layer = NULL; + if (jaggl_layer) { + [jaggl_layer removeFromSuperlayer]; + [jaggl_layer release]; + jaggl_layer = NULL; + } } }); - if (jaggl_onscreen_context) { + if (jaggl_calayer && jaggl_onscreen_context) { CGLDestroyContext(jaggl_onscreen_context); jaggl_onscreen_context = NULL; } @@ -750,7 +762,9 @@ JNIEXPORT jboolean JNICALL Java_jaggl_context_swapBuffers(JNIEnv *env, jclass cl #elif defined(_WIN32) result = (jboolean) SwapBuffers(jaggl_device); #elif defined(__APPLE__) && defined(__MACH__) - [jaggl_layer blit]; + if (jaggl_calayer) { + [jaggl_layer blit]; + } /* * This buffer swap isn't strictly necessary (in fact, I'm not sure if we @@ -796,7 +810,9 @@ JNIEXPORT void JNICALL Java_jaggl_context_setSwapInterval(JNIEnv *env, jclass cl #elif defined(__APPLE__) && defined(__MACH__) GLint param = (GLint) interval; CGLSetParameter(jaggl_context, kCGLCPSwapInterval, ¶m); - CGLSetParameter(jaggl_onscreen_context, kCGLCPSwapInterval, ¶m); + if (jaggl_calayer) { + CGLSetParameter(jaggl_onscreen_context, kCGLCPSwapInterval, ¶m); + } #else #error Unsupported platform #endif @@ -1066,11 +1082,12 @@ JNIEXPORT jboolean JNICALL Java_jaggl_context_choosePixelFormat1(JNIEnv *env, jc result = JNI_TRUE; #elif defined(__APPLE__) && defined(__MACH__) - id platformInfo = (id) dsi->platformInfo; - if (!platformInfo) { + if (!dsi->platformInfo) { goto dsi_free; } + jaggl_calayer = awt.version & (jint) JAWT_MACOSX_USE_CALAYER; + for (int i = 0; i < 2; i++) { bool double_buffered = i == 0; @@ -1109,34 +1126,41 @@ JNIEXPORT jboolean JNICALL Java_jaggl_context_choosePixelFormat1(JNIEnv *env, jc jaggl_double_buffered = double_buffered; jaggl_alpha_bits = alpha_bits; - CGLCreateContext(jaggl_pix, NULL, &jaggl_onscreen_context); - if (!jaggl_onscreen_context) { - CGLDestroyPixelFormat(jaggl_pix); - goto dsi_free; - } + if (jaggl_calayer) { + id platformInfo = (id) dsi->platformInfo; - dispatch_sync(dispatch_get_main_queue(), ^{ - NSRect frame = NSMakeRect(0, 0, dsi->bounds.width, dsi->bounds.height); - jaggl_view = [[NSView alloc] initWithFrame:frame]; - - jaggl_window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]; - jaggl_window.contentView = jaggl_view; - - jaggl_layer = [[JagGLLayer alloc] init]; - platformInfo.layer = jaggl_layer; - - /* - * XXX(gpe): the DSI bounds include the top/left insets, which we - * need to subtract here. Unfortunately, we can't access them here - * easily. Ignoring the left inset and hard-coding y to zero work, - * but only because windows don't have left borders and there is - * nothing above the Canvas in the Frame. - */ - jint x = dsi->bounds.x; /* should be dsi->bounds.x - insets.left */ - jint y = 0; /* should be dsi->bounds.y - insets.top */ - jaggl_layer.frame = NSMakeRect(x, platformInfo.windowLayer.bounds.size.height - y - dsi->bounds.height, dsi->bounds.width, dsi->bounds.height); - [jaggl_layer setNeedsDisplay]; - }); + CGLCreateContext(jaggl_pix, NULL, &jaggl_onscreen_context); + if (!jaggl_onscreen_context) { + CGLDestroyPixelFormat(jaggl_pix); + goto dsi_free; + } + + dispatch_sync(dispatch_get_main_queue(), ^{ + NSRect frame = NSMakeRect(0, 0, dsi->bounds.width, dsi->bounds.height); + jaggl_view = [[NSView alloc] initWithFrame:frame]; + + jaggl_window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]; + jaggl_window.contentView = jaggl_view; + + jaggl_layer = [[JagGLLayer alloc] init]; + platformInfo.layer = jaggl_layer; + + /* + * XXX(gpe): the DSI bounds include the top/left insets, which we + * need to subtract here. Unfortunately, we can't access them here + * easily. Ignoring the left inset and hard-coding y to zero work, + * but only because windows don't have left borders and there is + * nothing above the Canvas in the Frame. + */ + jint x = dsi->bounds.x; /* should be dsi->bounds.x - insets.left */ + jint y = 0; /* should be dsi->bounds.y - insets.top */ + jaggl_layer.frame = NSMakeRect(x, platformInfo.windowLayer.bounds.size.height - y - dsi->bounds.height, dsi->bounds.width, dsi->bounds.height); + [jaggl_layer setNeedsDisplay]; + }); + } else { + struct jaggl_legacy_dsi *platformInfo = (struct jaggl_legacy_dsi *) dsi->platformInfo; + jaggl_view = platformInfo->view; + } result = JNI_TRUE; goto dsi_free;